在汇编里,内中断有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