问题:用7ch中断例程完成loop指令的功能
loop s的执行需要两个信息,循环次数和到s的位移,loop指令的功能,也需要这两个信息作为参数。我们用cx位移。
所以,7ch中断例程要完成存放循环次数,用bx存放
应用举例;在屏幕中间显示80个'!'
assume cs:code code segment start: ;省略了前面的中断程序的安装 mov ax,0b800h mov es,ax mov di,160*12 mov bx,offset s-offset se ; bx存放转移位移 mov cx,80 ; 计数器 s: mov byte prt es:[di],'!' ; 显示缓冲区存放! add di,2 int 7ch ; 如果cx≠0 就跳转到标号s处执行 se : nop mov ax,4c00h int 21h ;7ch中断例程如下 lp: push bp mov bp,sp ; 将栈顶的ip送入bp 中 现在栈的数据依次为 bp 、ip、cs、flag寄存器 dec cx ; cx每次执行 自减 jcxz over add [bp+2],bx ;cx≠0 我们就修改cs:ip指向s处 将转移的位移bx + 入栈的se处的ip 为s 处的ip over : pop bp iret ; 依次恢复ip、cs、flag寄存器的值 code ends end start
在上面的程序中,用int 7ch调用7ch中断例程进行转移,用bx传递转移的位移。
分析:为了模拟loop指令,7ch中断例程应具备下面的功能。
(1) dec cx;
(2)如果cx≠0 ,转到标号s处执行,否则向下执行。
下面我们分析7ch中断例程如何实现到目的地址的转移。
(1)转到标号s显然应设(CS)=标号s的段地址,(IP)=标号s的偏移地址。
(2)那么,中断例程如何得到标号s的段地址和偏移地址呢?
int 7ch引发中断过程后,进入7ch中断例程,在中断过程中,当前的标志寄存器、CS和IP都要压栈,此时压入的CS和IP中的内容,分别是调用程序的段地址(可以认为是标号s的段地址)和int 7ch后一条指令的偏移地址(即标号se的偏移地址)。
可见,在中断例程中,可以从栈里取得标号s的段地址和标号se的偏移地址,而用标号se的偏移地址加上bx中存放的转移位移就可以得到标号s的偏移地址。
(3)现在知道,可以从栈中直接和间接地得到标号s的段地址和偏移地址,那么如何用它们设置CS:IP呢?se从
可以利用fret指令,我们将栈中的se的偏移地址加上bx中的转移位移,则栈中的的偏移地址就变为了s的偏移地址。我们再使用fret指令,用栈中的内容设置CS, IP,而实现转移到标号s处。
7ch中断例程如下
;7ch中断例程如下
lp: push bp
mov bp,sp ; 将栈顶的ip送入bp 中 现在栈的数据依次为 bp 、ip、cs、flag寄存器
dec cx ; cx每次执行 自减
jcxz over
add [bp+2],bx ;cx≠0 我们就修改cs:ip指向s处 将转移的位移bx + 入栈的se处的ip 为s 处的ip
over : pop bp
iret ; 依次恢复ip、cs、flag寄存器的值
因为要访问栈,使用了by,在程序开始处将by入栈保存,结束时出栈恢复。当要修改栈中se的偏移地址的时候,栈中的情况为:栈顶处是by原来的数值,下面是se的偏移地址,再下面是s的段地址,再下面是标志寄存器的值。而此时,by中为栈顶的偏移地址,所以((ss)* 16+(bp)+2)处为se的偏移地址,将它加上bx中的转移位移就变为s的偏移地址。最后用fret出栈返回,CS:IP即从标号s处开始执行指令。
如果(cx卜0,则不需要修改栈中se的偏移地址,直接返回即可。CPU从标号se处向下执行指令。
检测点13.1
上面内容中 7ch 实现的loop功能 所能进行的最大转移位移是多少?
分析: bx中存放转移的位移范围为 0~FFFF 所以能进行的转移位移为-32768~32767 最大转移位移是32767
用7ch中断例程完成jmp near ptr s 指令的功能 用bx向中断例程传送转移位移
在屏幕的第12行显示data段中 以0结尾的字符串
assume cs:code data segement db 'conversation',0 data ends code segment start : mov ax,data mov ds,ax mov si,0 mov ax,0b800h mov es,ax mov di,12*160 s: cmp byte ptr [si],0 je ok ;如果是0跳出循环 mov al,[si] mov es:[di],al inc si add di,2 mov bx,offset s - offset ok ; 设置从标号ok到标号s的转移位移 int 7ch ; 转移到标号s处 ok: mov ax,4c00h int 21h jp : push bp mov bp,sp ; 将栈顶的ip送入bp 中 现在栈的数据依次为 bp 、ip、cs、flag寄存器 add [bp+2],bx ; 我们就修改cs:ip指向s处 将转移的位移bx + 入栈的se处的ip 为s 处的ip over : pop bp iret ; 依次恢复ip、cs、flag寄存器的值 code ends end start