首先看转移指令jmp
先来看下相关代码
assume cs:codesg
codesg segment
start: mov ax,0
mov bx,0
jmp short s ;转移到s:处执行 inc ax,及跳过了add ax,1
add ax,1
s: inc ax
mov 4c00h
int 21h
codesg ends
end start
然后用debug运行一下,可以得到下图
可以注意到的是转移指令jmp的机器码为EB 03 , 并 不 包 含 \textcolor{red}{并不包含} 并不包含转移的目的地址 076A:000B,所以CPU是如何知道将ip改为多少呢?
事实上jmp short指令包含了转移的位移,上图中位移即为03,可以发现8与B之间恰好相差03,那为什么不是B-6=5呢?
这里就需要注意cpu执行指令的过程,如下
1. c p u 从 C S : I P 指 向 的 内 存 单 元 读 取 指 令 , 读 取 的 指 令 进 入 指 令 缓 冲 器 \textcolor{orange}{1.cpu从CS:IP指向的内存单元读取指令,读取的指令进入指令缓冲器} 1.cpu从CS:IP指向的内存单元读取指令,读取的指令进入指令缓冲器
2. I P = I P + 所 读 取 指 令 的 长 度 , 从 而 指 向 下 一 条 指 令 \textcolor{orange}{2.IP=IP+所读取指令的长度,从而指向下一条指令} 2.IP=IP+所读取指令的长度,从而指向下一条指令
3. 执 行 指 令 \textcolor{orange}{3.执行指令} 3.执行指令
可以发现当执行jmp指令是IP已经发生了移动,故此时计算位移得到03而不是05.
转移指令总结
offset 标号
start: mov ax,offset start ;
s: mov ax,offest s ;获得s的偏移地址 相当于 mov ax,3
jmp short 标号
;段内转移中的短转移 ,转移至标号处执行指令 偏移地址 -128~127
jmp near ptr 标号
;段内转移中的近转移 ,转移至标号处执行指令 偏移地址 -32768~32767
jmp far ptr 标号
;段间转移,转移至标号处执行指令 同时修改CS与IP 例如其机器码为EA0B01BD0B 即CS=0BBDH IP=010BH
jmp 16位reg
;IP=(16位reg)
jmp word ptr 内存单元地址(段内转移)
mov ax,0123H
mov ds:[0],ax
jmp word ptr ds:[0] ;IP=0123H
jmp dword ptr 内存单元地址(段间转移)
mov ax,0123H
mov ds:[0],ax
mov word ptr ds:[2],0
jmp dword ptr ds:[0] ;IP=0123H CS=0
jcxz 标号( 短转移)
;如果cx=0,转移至标号处执行,反之什么也不做
ret(近转移)
;相当于执行 POP IP
;1.(IP)=((ss)*16+(sp))
;2.(sP)=sP+2
retf(段间转移)
;相当于执行 POP IP POP CS
call 标号(近转移)
;相当于push IP jmp near ptr 标号
;1.(sp)=(sp)-2
;2.((ss)*16+(sp))=(IP)
;3.(IP)=(IP)+16位位移
call far ptr 标号(段间转移)
;push CS
;push IP
;jmp far ptr 标号
call word ptr 内存单元
;相当于 push IP jmp word ptr 内存单元
mov sp,10h
mov ax,0123h
mov ds:[0],ax
call word ptr ds:[0] ;IP=0123H sp=0EH
call dword ptr 内存单元
;push CS
;push IP
;jmp dword ptr 内存单元
注意call与ret可以互相配合来构造子程序
call s
...
...
s: ...
...
ret
检测比较结果的条件转移指令
所有的条件转移指令都为短转移,位移 -128~127
指令 | 含义 | 检测的相关标志位 |
---|---|---|
je | 等于则转移 | zf=1 |
jne | 不等于则转移 | zf=0 |
jb | 低于则转移 | cf=1 |
jnb | 不低于则转移 | cf=0 |
ja | 高于则转移 | cf=0且zf=0 |
jna | 不高于则转移 | cf=1或zf=1 |
上述指令通常与cmp配合使用
cmp ax,常数
je/ja/jb s