汇编语言-内中断

时间:2020-12-01 01:32:17

在汇编里,内中断有4种:除法错误、单步执行...

CPU处理内中断的思路和子程序差不多,首先也要知道中断后再处理什么程序,这个会根据一个8位的中断类型码来决定。通过中断类型码去查找一个中断向量表,这个向量表里会存储对应要执行程序的段地址和偏移地址。这个中断向量表在8086里默认放在内存0000:0000-0000:03FF的1024个字节中。

中断过程如下:

(1)取得中断类型码N

(2)pushf //将标志寄存器入栈

(3)TF = 0,IF = 0

(4)push CS

(5)push IP

(6)(IP) = (N*4),(CS) = (N*4+2)

1)除法错误

中断类型码为0.

如果想要修改发生除法错误的程序,也就是新写一个执行程序,并修改向量表对应的地址。

为了应对随时可能出现的除法错误,需要将执行程序保留在内存中。由于内存0000:0200-0000:02FF的256个字节一般空着,可以把执行程序复制到这里。

所以要做的是:将写好的执行程序复制到内存0000:0200后面的一段空间,参考代码如下。

要注意的几个地方是:

(1)将某位置的一段代码复制到另一位置,其实还是一个字节一个字节的搬。汇编里提供了一个串传送指令movsb/movsw,可以实现自动字节/字复制(结合标志寄存器里的DF标志),要实现多字节/字复制,就要用到loop,但汇编里还提供了一个rep指令,结合两者就可以很方便地实现代码复制了。

这里再仔细介绍下rep movsb的工作原理:

movsb相当于:

mov es:[di],cs:[si]

if df == 0: di++,si++

else di--,si--

所以使用movsb前要先设置好df,汇编语言里cld就是令df=0,std就是令df=1(相当于逆向传送)

rep movsb就相当于写了个loop,还是需要设置cx。

(2)比如想在执行代码里输出一段字符,那这段字符应该存在哪里呢,如果按照以前那样直接定义一个data segment,随着程序的运行,原先的data segment很容易被覆盖,因此最好将其存在执行代码中。

assume cs:code
code segment
start:    
    mov ax,cs mov ds,ax mov si,offset do0 mov ax,0 mov es,ax mov di,200h mov cx,offset do0end - offset do0 cld rep movsb mov ax,0 mov es,ax mov word ptr es:[0*4],200h mov word ptr es:[0*4+2],0 mov ax,1000 mov bh,1 div bh mov ax,4c00h int 21h do0: jmp short do0start db "overflow!" do0start:mov ax,0 mov ds,ax mov si,202h mov ax,0b800h mov es,ax mov di,12*160+36*2 mov cx,9 s: mov al,[si] mov es:[di],al mov byte ptr es:[di+1],0CAh inc si add di,2 loop s mov ax,4c00h int 21h do0end: nop code ends end start

2)单步执行

中断类型码为1.

如果检测到TF为1,则执行。这就是为什么执行中断时需要将TF置0,否则进入中断后检测到TF为1又要进行中断,无限循环...

3)int指令

int n就表示进行中断类型码为n的中断。

int和call类似,都是要求去执行另一段程序,对应的,call和ret组队,int和iret组队。

也就是说在子程序的结束处也需要加iret,其相当于执行

pop ip

pop CS

popf

举个栗子:用7ch中断例程完成loop指令的功能。

先给出应用场景:在屏幕中间显示80个'!'。

从下面的程序可看出,这里执行int 7ch后相当于将ip=s的偏移地址(if cx > 0)。但是在执行int 7ch时ip=se的偏移地址,因此其子程序相当于将ip += bx,这里的bx就是se到s的位移。

assume cs:code
code segment
start:    mov ax,0b800h mov es,ax mov di,160*12 mov bx,offset s - offset se mov cx,80 s: mov byte ptr es:[di],'!' add di,2 int 7ch se: nop mov ax,4c00h int 21h code ends end start

所以给出安装程序如下:

assume cs:code
code segment
start:    
    mov ax,cs mov ds,ax mov si,offset do0 mov ax,0 mov es,ax mov di,200h mov cx,offset do0end - offset do0 cld rep movsb mov ax,0 mov es,ax mov word ptr es:[7ch*4],200h mov word ptr es:[7ch*4+2],0 mov ax,4c00h int 21h do0: push bp mov bp,sp dec cx jcxz do1 add [bp+2],bx do1: pop bp iret do0end: nop code ends end start