要做的事情
- 1、编写可以显示 "overflow" 的中断处理程序 :
do0
- 2、将
do0
送入内存0000:0200H
开始处,即从内存单元0000:0200H
开始存放 0号中断处理程序本身
- 3、将
do0
的入口地址 0000:0200H
存储在 中断向量表 0号表项(内存单元 0000:0000~0000:0003H)
事情做完后得到的东西
从0号表项读取0号中断处理程序的入口地址 从入口地址处开始执行0号中断处理程序.png
程序框架
assume cs:code
code segment
start: do0安装程序
设置中段向量表
mov ax,4c00H
int 21H
do0: 显示字符串“overflow!”
mov ax,4c00H
int 21H
code ends
end start
实现 do0 的安装程序
- 功能:执行do0的安装程序后,会将do0的代码复制到内存0000:0200H处
do0安装代码实现
设置ds:si指向源地址 do0 程序本身所在 【cs:标号do0】
设置es:di指向目的地址 中断向量表的【0000:0200】
设置cx为传输长度
设置传输方向为正
rep movsb
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,4c00H
int 21H
do0: 显示字符串“overflow!"
mov ax,4c00H
int 21H
do0end: nop
code ends
end start
- 要使用
rep movsb
,必须是ds:si 指向源地址
、es:di 指向目的地址
且结合cx
-
mov si,offset do0
得到标号 do0的偏移地址(原始地址的偏移地址)
-
mov cx,offset do0end - offset do0
计算得到 do0所有指令的字节数(do0代码长度)
实现 do0 中断处理程序本身
- 功能:在除法溢出发生时,在屏幕上显示字符串“overflow!”
do0程序本身代码实现
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,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
-
"overflow!"字符串 放在 do0程序的开始处
do0: jmp short do0Start
db 'overflow!'
mov ax,cs
mov ds,ax
mov si,202H
段地址
"overflow!" 和 do0的代码处于同一个段中,
发生除法溢出的时候,do0的段地址就是CS
所以需要把 ds 设置成 CS
偏移地址
0000:0200H 处的指令是 jmp short d0start
这条jmp指令占两个字节,
所以"overflow!"的偏移地址是 202H
设置中断向量
- 功能:在中断向量表的0号表项处填入0号中断处理程序的入口地址
0000:0020H
mov ax,0
mov es,ax
mov word ptr es:[0*4],200H
mov word ptr es:[0*4+2],0
完整源码 : do0.asm
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,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 ah,02H
mov cx,9
s: mov al,[si]
mov es:[di],al
mov es:[di+1],ah
inc si
add di,2
loop s
mov ax,4c00H
int 21H
do0end: nop
code ends
end start
- 方便看结果,对于“overflow”的显示增加了样式:绿色
mov ah,02H ;绿色
mov cx,9
s: mov al,[si]
mov es:[di],al
mov es:[di+1],ah ;设置属性
测试程序 : testdo0.asm
assume cs:code
code segment
start: mov ax,0FFFFH
mov bh,1
div bh
mov ax,4c00H
int 21H
code ends
end start
调试测试程序
masm do0.asm
link do0.obj
debug do0.exe
使用 debug 【g命令】一步到位执行完全部指令
以看到下面的结果为准:
(一)在中断处理向量表的0号表项填入入口地址,
前四个内存单元应该是 00 02 00 00 组成 0000:0200H;
(二)0号中断处理程序被写入内存0000:0020H开始的地址。
- 2、编译、连接、调试,文件
testdo0.asm
masm testdo0.asm
link testdo0.obj
debug testdo0.exe
使用debug【u命令】查看 mov ax,4c00H所在内存单元的偏移地址X
使用debug【g命令】 g X 直接跳转到这个地址就可以看输出结果
以看到下面的结果为准:
(一)在运行testdo0.exe 率先查看中断处理向量表的状态,
要求入口地址以及处理程序都被正确填写了;
(二)本程序中的 mov ax,4C00H 语句所在内存单元偏移地址是 0007H,
因此使用的【G命令】是 g 7 (如图);
(三)屏幕上出现绿色的字符串 “overflow!” 。
调试过程图解
0、文件结构,同一文件目录下 编译连接调试工具 与 自己编写的源码文件.png
2 调试测试程序 此时内存已经安装好了0号中断处理程序.png
3、运行测试程序 用g命令直接跳到 mov ax 4c00H 处 显示overflow.png