先说明下无符号除法
指令为 DIV
格式:DIV OPRD
如果:OPRD
为单字节即 BL CL
则:AX/OPRD
结果:AL=商,AH=余数
如果:OPRD
为双字节 BX,CX
则:DXAX/OPRD
结果:AX=商,DX=余数
如果除法发生错误会产生0
号中断,我们今天要做的就是将0
号中断给改了。
我们之前知道80x25
为彩色缓冲区,那么我们可以往这个区域直接写字符就能显示在屏幕上。
DATAS SEGMENT
;此处输入数据段代码
DATAS ENDS
STACKS SEGMENT
;此处输入堆栈段代码
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX
mov ax,0
mov bx,1
mov dx,1
div bx
MOV AH,4CH
INT 21H
CODES ENDS
END START
我们直接运行上面除法发现程序报错显示在左上角
我们现在将int0
中断的提示信息移动到屏幕中间并显示红底蓝字。代码如下:
DATAS SEGMENT
;此处输入数据段代码
DATAS ENDS
STACKS SEGMENT
;此处输入堆栈段代码
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX
call cpy_new_int0 ;自定义中断的函数拷贝到安全区域
call chang_int0 ;变更中断向量表中中断0所存的入口指针
mov ax,0
mov dx,1
mov bx,1
div bx ;DXAX/BX 商在AX中,余数在DX中
MOV AH,4CH
INT 21H
;================================================
chang_int0:
mov ax,0
mov es,ax ;设置数据到哪里去,一个函数指针4个字节
mov word ptr es:[0*4],7E00H ;低2个字节给ip
mov word ptr es:[0*4+2],0 ;高2个字节给cs
ret
;================================================
new_int0:
jmp newInt0
string: ;用于辅助计算数据起始位置,使用OFFSET string-new_int0得到字符串从什么位置开始读取
db 'divide error',0 ;结尾0用于辅助判断数据读到什么位置结束
newInt0:
mov bx,0B800H ;数据写到80x25彩色缓冲区
mov es,bx
mov di,160*10+30*2 ;写在缓冲区的起始位置第10行第60个字节开始
mov bx,0 ;数据从哪里来
mov ds,bx
mov si,OFFSET string-new_int0 +7E00H ;由于我们的new_int0-new int0_end 代码被复制到了7E00H起始的位置,所以前面计算的偏移量要加上这个值
showStr:
mov dl,ds:[si] ;显示 从si位置读取一个字节
cmp dl,0 ;判断是否读到0如果已读到0则结束未读到0则继续
je showStrRet
mov es:[di],dl ;将读到的字节写给缓冲区的偶数字节
mov bx,01000001B
mov es:[di+1],bx ;设置奇数字节为红底蓝字
add di,2 ;因为缓冲区2个字节表示一个字符,所以加2
inc si ;读取下一个字节
jmp showStr ;无条件循环
showStrRet:
MOV AH,4CH
INT 21H
new_int0_end: nop ;辅助计算需要被拷贝的代码结尾
;================================================
cpy_new_int0: ;拷贝代码
mov bx,cs ;取代码断地址
mov ds,bx ;设置数据从代码断来
mov si,OFFSET new_int0 ;数据起始位置
mov bx,0 ;数据复制到0:7E00H的位置
mov es,bx
mov di,7E00H
mov cx,OFFSET new_int0_end-new_int0 ;计算复制的总字节数即循环次数
cld ;设置DF=0 ,0表示si di 自增1,DF=1则相反si di自减 1
rep movsb ;重复操作,rep指令就是重复将ds[si]的数据搬到es[di]中,知道cx为0
ret
;================================================
CODES ENDS
END START
然后我反注释回来,在执行发现结果如下,说明我们已经修改了int0
中断为我们自己的程序