9 转移指令的原理
[TOC]
可以修改IP, 或同时修改CS和IP的指令统称为转移指令。
8086CPU的转移行为有以下几类:
- 只修改IP时,称为段内转移。如
jmp ax
- 同时修改CS和IP时, 称为段间转移,比如:
jmp 1000:0
转移指令对IP的修改范围不同,段内转移可进一步分为:短转移和近转移
- 短转移IP的修改范围是
-128~127
- 近转移IP的修改范围为
-32768~23767
8086CPU的转移指令分为以下几类:
- 无条件跳转指令(如
jmp
)- 条件转移指令(如
jnz
)- 循环指令(如
loop
)- 过程 (如
call
,ret
)- 中断(
int
)
操作符offset
操作符offset在汇编语言中是由编译器处理的符号,它的功能是取得标号的偏移地址。比如下面的程序:
assume cs:codesg
codesg segment
start: mov ax, offset start; 相当于mov ax, 0
s: mov ax, offset s ;相当于mov ax, 3; 我不清楚一条指令到底多长,这种情况下加个标号,使用offset 就可以了。编译器会帮你计算。想知道对应指令的机器码可以用debug查看。
codesg ends
end start
jmp指令
无条件跳转指令,可修改IP,也可同时修改CS和IP。
jmp指令要给出两种信息:
- 转移的目的地址。
- 转移的距离(段间转移、段内短转移、段内近转移)
总结
目的地址 | 示例 | 说明 |
---|---|---|
无,有偏移地址 | jmp short 标号 |
偏移地址在机器码中 EBXXXX XXXX为偏移地址 |
有,在指令中 | jmp far ptr 标号 |
目的地址在机器码中 EAXXXXYYYY XXXX为段地址,YYYY为偏移地址 |
有,在寄存器中 | jmp 16位 reg |
目的地址在寄存器中。用于修改IP |
有,在内存中 |
依据位移进行转移的jmp指令
段内短转移:jmp short 标号
对IP的修改范围-128~127
CPU在执行jmp指令的时候并不需要转移的目的地址。
jmp short 标号
生成的机器码为EBXX, 其中XX指明了下一个指令和目标指令的偏移量。于是直接IP=IP+偏移量
就计算出了目的地址。
实际上,jmp short 标号
的功能为:(IP) = (IP)+8位位移。
- 8位位移=标号处的地址-jmp 指令后的第一个字节的地址;
- short 指令此处的位移为8位位移。
- 8位位移的范围为-128~127, 用补码表示。
- 8位位移由编译程序在编译时算出。。
类似的jmp near 标号
使用的位移为16位位移。
图实例:
转移的目的地址在指令中的jmp指令
jmp far ptr 标号
段间转移,跨段了,没法计算偏移量,所以必须制定目的地址了。
(cs)=标号所在段的段地址;(IP)=标号在段中的偏移地址。
jmp far ptr 标号
对应的机器码为EAXXXXYYYY
其中XXXX
为段地址,YYYY
为偏移地址。
转移地址在寄存器中的jmp指令
指令格式:jmp 16位 reg
功能:(IP)=(16位reg)
转移地址在内存中的jmp指令
两种形式:
- 段内转移
jmp word ptr 内存单元地址
内存单元存的偏移地址 - 段间转移
jmp dword prt 内存单元地址
内存单元存2个字,高地址是段地址,低地址是偏移地址。
jcxz指令
条件转移。jcxz 标号
类似jmp short 标号
也是把偏移地址放到指令中。
如果(cx)==0 跳转到标号。否则什么都不干,
loop指令
也是短转移。偏移地址放到指令中。
执行loop 标号
- (cx)=(cx)-1
- 如果(cx)!=0 跳转到标号。否则什么都不干。(程序向下执行)
根据位移进行转移的意义
总结下使用位移跳转的指令:
jmp short 标号
jmp near ptr 标号
jczx 标号
loop 标号
这种设计方便程序段在内存中浮动装配。
其实有虚拟内存之后。这个设计的意义感觉就不大了?
编译器对转移位移越界的检测
转移范围是-128-127
如果越界,编译器会报错。在Debug中不会。