实验8
分析下面程序,这个程序可以正确返回吗?
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指令的原理的理解
mov di,offset s
mov si,offset s2
mov ax,cs:[si]
mov cs:[di],ax
这4条指令的作用就是将s2标号地址的指令赋值到s标号地址
-
直接从s0标号地址指令开始分析
此时程序会跳转到s标号位置,而s标号地址我们已经知道现在存储的时s2标号地址指令
-
这里就考察对于
jmp 转移位移的指令的原理的理解先贴出其对应的机器指令

- 首先先回顾CPU执行指令的过程,比如下面中的指令
EB03
- 首先先回顾CPU执行指令的过程,比如下面中的指令


jmp 转移位移指令的转移位移的计算方法

- 清楚了上面的知识,再来观察ip

-
程序经过编译之后
-
s0标号地址的jmp指令计算的转移位移为F0(补码)=-16
-
s2标号地址的jmp指令计算的转移位移是程序还没有运行前的,所以转移位移为F6(补码)=-10
所以当执行完
mov cs:[di],ax时,ip=16h之后读取
jmp short s后,ip+=2,等于18h也就是24之后执行指令ip+=-16,等于8
之后再读取s标号地址指令,注意此时已经为
EB F0(也就是jmp short s1编译的机器指令),ip+=2,等于0ah也就是10之后再执行指令ip+=-10,等于0
-
-
程序执行之后变为

汇编编译器(masm.exe)对jmp的相关处理
1.向前转移
s: .
.
jmp s ( jmp short s、 jmp near ptr s、 jmp far ptr s)
编译器中有一个地址计数器(AC,编译器在编译程序过程中,每读到一个字节AC就加1。当编译器遇到一些伪操作的时候,也会根据具体情况使AC增加,如db、dw等。
在向前转移时,编译器可以在读到标号s后记下AC的值as,在读到jmp….s后记下AC的值aj。编译器就可以用as-aj算出位移量disp。
2.向后转移
jmp s( jmp short s、 jmp near ptr s、 jmp far ptr s)
.
.
s:
在这种情况下,编译器先读到jmp….s指令。由于它还没有读到标号s,所以编译器此时还不能确定标号s处的AC值。也就是说,编译器不能确定位移量disp的大小。
此时,编译器将jmp….s指令都当作 jmp short s来读取,记下jmp….指令的位置和AC的值a,并作如下处理。
- 对于 jmp short s,编译器生成EB和I个nop指令(相当于预留1个字节的空间,存放8位disp);
- 对于jmp s和 jmp near ptr s,编译器生成EB和两个nop指令(相当于预留两个字节的空间,存放16位disp)
- 对于 jmp far ptr s,编译器生成EB和4个nop指令(相当于预留4个字节的空间,存放段地址和偏移地址)
作完以上处理后,编译器继续工作,当向后读到标号s时,记下AC的值as,并计算出转移的位移量:disp=as-aj
深入理解JMP指令
本文详细解析了JMP指令在汇编语言中的工作原理,通过具体实验程序,展示了向前和向后转移时,汇编编译器如何计算位移量,并生成相应的机器指令。深入探讨了masm.exe在编译过程中的处理方式。
968

被折叠的 条评论
为什么被折叠?



