学习汇编已有两三月了,后面的东西已是渐渐看着比较吃力,花了点时间将书中的第十五章的实例进行了细致解读,并注释了一下,达到一目了然的效果,一来:为自己存一份,免得哪时又忘了!二来:可以为不懂的童鞋一个借鉴。
assume cs:code
stack segment
db 128 dup(0)
stack ends
data segment
dw 0,0
data ends
code segment
start: mov ax,stack
mov ss,ax
mov sp,128 ;设置栈
mov ax,data
mov ds,ax
mov ax,0
mov es,ax
;-------将原int 9例程进行保存-----------
push es:[9*4] ;将原int 9中断例程地址的偏移地址压栈
pop ds:[0] ;将中断例程地址的偏移地址放入data段中
push es:[9*4+2] ;将原int 9中断例程地址的偏移地址入栈
pop ds:[2] ;将中断例程地址的段地址放入data段中
;-------在中断向量表中设置新的中断例程入口地址---------
mov word ptr es:[9*4],offset int9
mov es:[9*4+2],cs ;在中断向量表中设置新的int 9中断例程的入口地址
;--------将a-z字母显示到屏幕中-------------
mov ax,0b800h
mov es,ax
mov ah,'a'
s:mov es:[160*12+80],ah
call delay ;进行循环100000h次,用于查看字符
inc ah
cmp ah,'z'
jna s
;--------将原中断向量表复原--------------
mov ax,0
mov es,ax
push ds:[0]
pop es:[9*4]
push ds:[2]
pop es:[9*4+2] ;将中断向量表中int 9中断例程的入口恢复为原来的地址
mov ax,4c00h
int 21h
;------将循环100000h次,以拖延程序的执行时间-----------
delay: push ax ;做程序的延迟,其中有人对为什么执行了1000000h次存在疑惑,详见附录
push dx
mov dx,1000h
mov ax,0
s1: sub ax,1
sbb dx,0
cmp ax,0
jne s1
cmp dx,0
jne s1
pop dx
pop ax
ret
;-------以下为新的int 9中断例程--------
int9: push ax
push bx
push es ;将要用到的寄存器先进行压栈
in al,60h ;取得键盘端口的数据
pushf ;将状态寄存器压栈
pushf
pop bx
and bh,11111100b
push bx
popf ;将TF和IF置为0
call dword ptr ds:[0] ;对int指令进行模拟,调用原来的int9中断例程,实现检测输入按键的处理
cmp al,1 ;检验是否为esc键
jne int9ret ;如果不是esc键,则返回,如果不是,则进行下一步操作!
mov ax,0b800h
mov es,ax
inc byte ptr es:[160*12+40*2+1] ;对属性值加1,用于改变颜色
int9ret: pop es
pop bx
pop ax
iret
code ends
end start
附录:其中有人对为什么执行了1000000h次存在疑惑,我这;;儿大致讲解一下,因为ax为0,而执行sub ax,1后,ax就成了FFFFh了,所以等到ax再次为1的时候,它被执行了10000h次了,而s1程序实际是在执行两个循环,一个外一个内,刚才那是内循环执行了10000h次,外循环又执行了10h次,所以它们总共就执行了1000000h次。
转载于:https://blog.51cto.com/rainnight/1177100