assume cs:code,ss:stack
stack segment
db 128 dup (0)
stack ends
code segment
start:
mov ax,cs ;开始安装 0 号中断的中断处理程序
mov ds,ax ;所谓的安装, 就是将do0子程序代码复制到一段内存区域, 这段内存区域是完全安全的
mov si,offset do0 ;设置 ds:si 指向要复制的子程序的起始地址
mov ax,0
mov es,ax
mov di,200h ;设置 es:di 指向该中断处理程序在内存中的起始地址
mov cx,offset do0end-offset do0 ;计算要复制的中断处理程序有多长
cld ;设置复制方向为正
rep movsb ;进行代码的赋值
mov word ptr es:[0*4],200h ;将中断处理程序的首地址注册在中断向量表的对应表项中, 将中断例程安装在 0:200h 是由编程人员决定的
mov word ptr es:[0*4+2],0
mov dx,152 ;一个检测程序
mov ax,0
mov cx,2
div cx ;执行后, 发生除法溢出, 从而进行中断相关的工作
# 要注意的是下面的中断处理程序在本程序执行的时候并不会执行
# 只有在发生中断的时候才会执行, 并且执行的也不是这段代码
# 而是执行已经经过上面的代码复制到 0:200h 处的中断处理程序
# 所以下面的这一片只是为了复制而用的
do0:jmp short do0start ;因为下一段代码只是数据的定义, 不是 CPU 能够识别的指令, 所以需要跳过
db 'divide error!'
do0start:
mov ax,cs ;因为 do0 已经被安装到了 0:200h 处, 所以 cs 中的值应为 0
mov ds,ax
mov si,202h ;因为 do0 标号处的指令占有 2 字节, 所以 ds:[202h] 指向字符串的开始位置
mov ax,0b800
mov es,ax
mov di,160*12+34*2 ;设置字符串要显示的目的地址(显示缓冲区的一段空间)
mov cx,13 ;循环 13 次
dnext:
mov al,[si]
mov es:[di],al ;移动字符本身
mov es:[di+1],81h ;设置第二个字节, 即字符显示的颜色
inc si ;源字符的偏移量一次增加一个字节
add di,2 ;目的字符的偏移量一次增加两个字节, 因为还有一个颜色属性字节
loop dnext
mov ah,4c ;返回 DOS
int 21h
do0end:nop
code ends
end start