书上解析的很详细,只需要我们把各步综合在一起就ok啦。
首先我们写一个overflow除法溢出程序。
assume cs:code
code segment
start:mov ax,1000
mov bh,1
div bh
mov ax,4c00h
int 21h
code ends
end start
方便debug直接跟踪。
然后是改写0号中断处理程序的代码:
;编写0号中断的处理程序,发生除法溢出时,在屏幕中间显示字符串“divide error!”,然后返回到dos
;先设置中断向量表,将do0指令送入0:200处,再执行do0
assume cs:code
code segment
start:
mov ax,cs
mov ds,ax
mov si,offset do0;ds:[si]就是do0的入口
mov ax,0
mov es,ax
mov di,200h;es:[di]是0:200
mov cx,offset do0end-offset do0;将do0至do0end的处IP值相减,实际上就是长度,然后设置循环将ds中的代码段送入es中
cld
rep movsb
mov ax,0
mov es,ax
mov word ptr es:[0*4],200h
mov word ptr es:[0*4+2],0;设置好0号中断的执行程序段地址以及偏移地址
mov ax,4c00h
int 21h
do0:jmp short do0start;占用2个字节,200和201
db "overflow!";这里从202开始一共九个字节
do0start:mov ax,cs
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:1[di],02h
inc si
add di,2
loop s
mov ax,4c00h
int 21h
do0end:nop;用来标定do0实际代码段的长度
code ends
end start
为了显眼,我加了个绿色。也就是02h那一行,实际可不用。
具体的解释我也写的比较清楚。
重点在于程序debug跟踪:运行该程序,只会将do0段的代码全部传送至目标地址中,然后设置好向量表中0号的地址。只有当我们再次运行overflow的时候,才会执行do0中的第一行代码段内转移。此后没什么问题,这个其实相当于链表和指针,do0是一个链表,而我们通过除法溢出后0号指针找到do0运行。do0中存储的是代码,这里可以用debug逐步跟踪d命令查看一下内存中的情况,会更加直观!
运行结果: