(2)编写并安装int 7ch中断例程,功能为完成loop指令的功能。
参数:(cx)=循环次数,(bx)=位移。
以上中断例程安装好后,对下面的程序进行单步跟踪,尤其注意int,iret指令执行前后cs,ip的和栈中的状态。
assume cs:code
code segment
start: mov ax, 0b800H
mov es, ax
mov di, 160*12
mov bx, offset s – offset se
mov cx, 80
s: mov byte ptr es:[di], '!'
add di, 2
int 7cH
se: nop
mov ax, 4c00H
int 21H
code ends
end start
程序分析:
为了模拟loop指令, 7ch中断例程必须具备下面功能
1、dec 程序
2、如果cx≠0,转到标号s处执行,否则继续向下执行
转移到标号s处需要设置CS = 标号s的段地址,IP = 标号s的偏移地址,我们知道,在7ch中断触发后,当前的标志寄存器、CS和IP都要压栈,此时压入的CS和IP中的内容分别是调用程序的段地址(可以认为是标号s的段地址)和7ch后一条指令的偏移地址(即标号se的偏移地址)
可见,在中断例程中,可以从栈里取得标号s的段地址和标号se的偏移地址, 而用标号se的偏移地址加上bx中存放的转移位移就可以得到标号s的偏移地址,至此,我们已经可以写出中断例程如下:
showstr:push bp
mov bp, sp
dec cx
jcxz ok
add [bp + 2], bx
ok:pop bp
iret
showend:nop
因为要访问栈,程序中使用了bp,开程序开始处将bp入栈保存, 结束时出栈恢复,当要修改栈中se的偏移地址的时候,栈中的情况如下图:
此时,栈顶为bp,所以se的偏移地址为ss*16+bp+2,将它加上bx中的转移位移就标为s的偏移地址,最后用iret出栈返回,CS:IP即从标号s处开始执行指令,如果cx=0,则不需要修改栈中se的偏移地址,直接返回即可。CPU从se处向下执行指令
完成源码如下:
assume cs:code
code segment
start:mov ax, cs
mov ds, ax
mov si, offset showstr
mov ax, 0
mov es, ax
mov di, 200h
mov cx, offset showend - offset showstr
cld
rep movsb
mov ax, 0
mov es, ax
mov word ptr es:[7ch*4], 200h
mov word ptr es:[7ch*4 + 2], 0
mov ax, 0b800h
mov es, ax
mov di, 160*12
mov bx, offset s - offset se
mov cx, 80
s:mov byte ptr es:[di], '!'
add di, 2
int 7ch
se:nop
showstr:push bp
mov bp, sp
dec cx
jcxz ok
add [bp + 2], bx
ok:pop bp
iret
showend:nop
mov ax, 4c00h
int 21h
code ends
end start
执行结果:
(3)下面的程序,分别在屏幕的第2、4、6、8行显示4句英文诗,补全程序。
程序源码为:
assume cs:code
code segment
s1: db 'Good, better, best,','$'
s2: db 'Never let it rest,', '$'
s3: db 'Till good is better,', '$'
s4: db 'And better, best.', '$'
s: dw offset s1, offset s2, offset s3, offset s4
row: db 2, 4, 6, 8
start:mov ax, cs
mov ds, ax
mov bx, offset s
mov si, offset row ;行数索引
mov cx, 4 ;共需要4行数据
ok:mov bh, 0 ;第0页
mov dh, [si] ;第几行
mov dl, 0 ;第几列
mov ah, 2 ;置光标功能
int 10h ;调用10h号中断处理程序的2号子程序
mov dx, [bx] ;在光标处显示字符串
mov ah, 9 ;调用21h号中断处理程序的9号子程序
int 21h
inc si
add bx, 2 ;dw定义字型数据,增量为2
loop ok
mov ax, 4c00h
int 21h
code ends
end start
程序执行结果:
题目灵活利用标号偏移地址指出各数据段的内存地址,其次,每次字符串都以$结尾,可利用21h中断的9号处理程序来完成题目要求