转移指令
# 8086cpu的转移指令分为以下几类:
* 无条件转移指令(如:jmp)
* 条件转移指令
* 循环指令(如:loop)
* 过程(相当于函数)
* 中断
# 操作符offset在汇编语言中是由编译器处理的符号,它的功能是取得标号的偏移地址
a. 无条件转移:
# jmp为无条件转移,可以只改变IP,也可以同时修改CS和IP
jmp指令要提供两条信息:
* 转移的目的地址
* 转移的距离(段间距离,段内短转移,段内近转移)
//==============================段内转移====================================
1)jmp short 标号 (转到标号处执行指令)
这种格式的jmp指令实现的是段内短转移,它对IP的修改范围为-128-127,即向前转移最多 可以越过128个字节,向后转移最多可以越过127个字节
assume cs:codesg
codesg segment
start: mov ax,0
jmp short s
add ax,1 //此处ax+1未执行,由jmp直接跳过了,所以最终ax为1
s:inc ax
codesg ends
end start
实际上,指令"jmp short 标号"的功能为ip=ip+8位位移
* 8位位移="标号"处的地址->jmp指令后的第一个字节的地址
* short指令表明此处的位移为8位位移
* 8位位移的范围为-128-127,用补码表示
* 8位位移由编译程序在编译时算出
2) jmp near ptr 标号(和jmp short 标号类似,不过是段内近转移)
指令"jmp near ptr 标号"的功能为ip=ip+16位位移
* 16位位移="标号"处的地址->jmp指令后的第一个字节的地址
* near指令表明此处的位移为16位位移
* 16位位移的范围为-32769-32768,用补码表示
* 16位位移由编译程序在编译时算出
3)jmp 16位寄存器
功能:IP=16位寄存器
4)jmp word ptr 内存单元地址
功能:从内存单元地址处开始存放一个字,是转移的目的的偏移地址
//==============================段间转移=======================================
1)jmp far ptr 标号(实现的是段间转移,又称为远转移)
功能:
* cs=标号所在段的段地址
* ip=标号所在段中的偏移地址
2)jmp dword ptr 内存单元地址
功能:从内存单元地址处开始存放两个字,高地址处的字是转移目的的段地址,低地址处是 偏移地址
b.有条件转移
1)jcxz指令
jcxz指令为有条件转移指令,所有的有条件转移指令都是短转移,在对应的机器码中包含转移的位移
而不是目的地址。对IP的修改范围都为-128-127
指令格式: jcxz 标号
如果cx=0,则转移到标号处执行,相当于(if(cx==0) jmp short 标号)
2)loop
loop为循环指令,所有的循环指令都是短转移,在对应的机器码中包含转移的位移,对ip的修改范围
为-128-127
指令格式:loop 标号
每次执行后cx=cx-1,如果cx!=0,则转移到标号处执行,与jcxz相反,相当于
if(--cx!=0)
jmp short 标号
!!!注意使用转移指令时,比如
assume cs:codesg
codesg segment
mov ax,4c00h
int 21h
start: mov ax,0
s: nop //什么也不做,占一个字节
nop
mov di,offset s //di保存s标志所在的偏移地址
mov si,offset s2 //si保存s2标志所在偏移地址
mov ax,cs:[si]
mov cs:[di],ax //将s标志处的机器码改为s2标志处的机器码,
s0: jmp short s //跳转到标志s处
s1: mov ax,0
int 21h
mov ax,0
s2: jmp short s1
nop
codesg ends
end start
来分析一下上面程序,从代码段的start标志开始执行:
1:mov ax,0
2:nop
3:nop
4:mov di,offset s
5:mov si,offset s2
6:mov ax,cs:[si]
7:mov cs:[di],ax /*这里将cs:[di]处的机器码改为cs:[si]的,看一
下cs:[si],si是标志s2处的偏移地址,s2处指令
为 jmp short s1
nop
由于转移指令不是记录偏移地址,而是转移的距离,编译器
算出地址,所以这里机器码中保存s2到s1的距离,由于
向上转移,所以是负的,大小为字节数,看一下debug
*/
第8步跳到标志s中(jmp short s),由于标志s处机器码已经改为s2处的机器码,所以再次跳转,注意不是跳转到s1,而是向上跳转10个字节,之所以用nop就是为了使得跳转的字节大小相同,所以应该跳转到
mov ax,4c00h
int 21h
程序结束