这段时间看王爽的汇编看的效率很高,看样在学习高级语言后再学习asm是速度比较快。其中有讲到指令跳转的地方,我当时想到的就是goto,用汇编来解释再贴切不过了。我贴上一道习题与讲解,加深印象。
---------------------------------
分析下面的程序,在运行前思考:这个程序可以正确返回吗?
运行后再思考:为什么是这种结果?
通过这个程序加深对相关内容的理解。
assume cs:codesg
codesg segment
mov ax,4c00h
int 21h
start:
mov ax,0
s:
nop
nop
mov di,offset s
mov si,offset s2
mov ax,cs:[si]
mov cs:[di],ax
s0:
jmp short s
s1:
mov ax,0
int 21h
mov ax,0
s2:
jmp short s1
nop
codesg ends
end start
-------------------------------------------------------------------------------------------------------------------------------------------------------
程序可以正常返回。
详细分析:
在此题中较为深入地考察了‘段内直接短转移’[形如:jmp short 标号]的概念。
我们知道程序中:
mov di,offset s
mov si,offset s2
mov ax,cs:[si]
mov cs:[di],ax
四条指令的作用是将标号s2处的一条指令复制到标号s处。这时我们应该关心所复制的语句"jmp short s1"对程序的影响:我们知道在段内直接短转移指令所对应的机器码中,并不包含转移的目的地址,而包含的是转移的位移量(如对此概念还不太熟悉,请查看书中第167页的内容)。也就是说,在源程序的编译过程中,编译器遇到‘段内直接短转移’[形如:jmp short 标号]时就会自动算出其要跳转的位移量,以便程序在执行‘段内直接短转移’的指令时就根据位移量进行(向前或向后)跳转。通过调试中的U命令我们可以看到指令's2:jmp short s1'所对应的机器码是EBF6,F6h(-10d的补码)就是跳转的位移量[此位移量也可由指令's2:jmp short s1'处的偏移地址18h减去指令's2:jmp short s1'后一个字节的偏移地址22h得出]。这时我们就知道了其实复制到标号s处的指令所对应的机器码就是EBF6(刚好取代两个nop所对应的机器码),它的作用就是将当前IP向前移动10个字节。当程序执行标号s0处的指令后,程序便跳到标号s处接着执行标号s处的指令。s处的指令的作用是向前跳10字节,于是便跳到了代码中的第一条指令,继续执行后便实现了程序的正常返回。
[注意:此程序不会也不可能执行标号s1处后的指令。]