大致的框架:
assume cs:code code segment start: do0安装程序 设置中断向量表 mov ax,4c00h int 21h do0: 显示字符串:"overflow!" mov ax,4c00h int 21h ;do0程序在这段程序中并不执行,只是作为数据传送到中断向量表中,即安装程序 code ends end start 安装中断程序的安装可以使用 rep movsb 来将do0的代码送入到0000:0200处;
大致框架:
assume cs:code code segment start: 设置es:di指向目的地址 设置ds:si指向源地址 设置cx的长度 设置传送方向为正 rep movsb 设置中断向量表 mov ax,4c00h int 21h do0: 显示字符串:"overflow!" mov ax,4c00h int 21h code ends end start使用 rep movsb 要确定的信息:
目的地址:0000:0200
源地址:code:offset do0
传送的长度cx: do0的代码的长度
传送方向为正: cld
因为do0的长度根据不同的序求需求会改变,没有必要每一次都计算,可以在最后加一个 do0end:nop,这样 mov cx,offset do0end-offset do0即可,"-"是编译器识别的运算符号,编译器可以用它来进行两个 常数 的减法,同时,也可以处理表达式;
最后的安装程序:
assume cs:code code segment start: mov ax,0 mov es,ax mov di,0200h ;目的地址 mov ax,cs mov ds,ax mov si,offset do0 ;源地址 mov cx,offset do0end-offset do0 cld rep movsb 设置中断向量表 mov ax,4c00h int 21h do0: 显示字符串:"overflow!" mov ax,4c00h int 21h do0end:nop code ends end start do0do0的任务是显示字符串,大致的框架:
do0: 设置ds:si指向字符串 mov ax,0b800h mov es,ax mov di,12*160+36*2 ;设置es:di指向显存空间中间位置 mov cx,9 ;设置cx为字符串长度 s: mov al,[si] mov es:[di],al inc si add di,2 loop s mov ax,4c00h int 21h do0end:nop这里的字符串的存放不能像之前的程序那样放在总程序的数据段中,因为当总程序运行完后数据段也就释放,不能保证中断程序所显示的字符串还是"overflow!";
所以要将字符串放在do0中,将其以通送到中断向量表的0000:0200处;
这样在发生除法溢出时,cs中存放的是do0的段地址,同时也是字符串的段地址,而因为程序要跳过字符串,不把他当作代码执行,所以在字符串之前要有一个jmp指令跳过字符串到实际的代码处,所以字符串的偏移地址就为0000:0200加2即0000:0202处(jmp占两个字节)
最后的程序:
do0: jmp short do0start db "overflow!" do0start: mov ax,cs mov ds,ax mov si,0202h ;设置ds:si指向字符串 mov ax,0b800h mov es,ax mov di,12*160+36*2 mov cx,9 s: mov al,[si] mov es:[di],al inc si add di,2 loop s mov ax,4c00h int 21h do0end:nop 设置中断向量设置中断向量即为将do0的入后地址0000:0200写入到中断向量表的0号表项中,使do0成为0号中断的中断处理程序;
0号表项的地址为0:0,其中0:0字单元存放偏移地址(ip),0:2字单元存放段地址(cs),
mov ax,0 mov es,ax mov word ptr es:[0*4],0200h mov word ptr es:[0*4+2],0综上,最后的程序如下:
assume cs:code code segment start: mov ax,0 mov es,ax mov di,0200h mov ax,cs mov ds,ax mov si,offset do0 mov cx,offset do0end-offset do0 cld rep movsb mov ax,0 mov es,ax mov word ptr es:[0*4],0200h mov word ptr es:[0*4+2],0 mov ax,1000h mov bh,1 div bh mov ax,4c00h int 21h do0: jmp short do0start db "overflow!" 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 inc si add di,2 loop s mov ax,4c00h int 21h do0end:nop code ends end start 单步中断CPU在执行完一条指令后,如果检测到标志寄存器的TF位为1,则产生单步中断,单步中断的中断类型码为1;
他引发的中断类型如下:
1、取得中断类型码1
标志寄存器入栈,TF、IF置0
CS,IP入栈
(IP)=(14),(CS)=(14+2)
使用t命令时,debug将TF设置为1,使得cpu执行完这条指令后引发单步中断;
执行单步中断的中断程序,所有寄存器的内容显示,等待输入;
中断处理程序也是由一条条指令组成的,如果在执行中断处理程序之前,TF=1,则CPU在执行完中断处理程序的第一条指令后,又要产生单步中断,则又要转去执行单步中断的中断处理程序…… ?
解决方法是在进入中断程序之前设置TF=0,也就是在前面说的中断过程中的第二步标志寄存器入栈后设置TF=0的原因;
CPU提供单步中断功能的原因就是,为单步跟踪的执行过程,提供了实现机制。
响应中断的特殊情况有些情况下,CPU在执行完当前指令后,即使发生中断,也不相应,例如:在执行完向ss寄存器传送数据的指令后,发生中断时,CPU也不会响应,因为,ss:sp联合指向栈顶,对他们的设置应该连续完成;