转移指令
可以修改cs:ip或只修改ip的指令称为转移指令;
因为cpu将cs:ip指向的数据当做指令来执行,因此转移指令就是可以控制cpu执行内存中某处代码的指令;
转移的分类:
1】 转移行为的分类:
只修改ip的称为段内转移;例如:jmp ax
同时修改cs:ip的称为段间转移;例如:jmp 1000:0
2】转移指令对ip的修改范围不同,段内转移分为短转移和近转移
短转移 ->修改ip范围为 -128~127;
近转移 ->修改ip范围为 -32768~32767;
3】转移指令的分类:
无条件转移指令;例如jmp
条件转移指令;
循环指令;例如loop
过程;
中断;
1.伪指令offset
offset由编译器执行,作用是获取标号的偏移地址;
例如:
assume cs:code
code segment
start:mov ax,offset start ;相当于mov ax,0
s:mov ax,offset s ;相当于mov ax,3
code ends
end start
因为start是第一条指令的标号,其偏移地址为0;
s是第二条指令的标号,第一条指令有3个字节,因此第二条指令的偏移地址是3;
2.jmp指令
jmp为无条件转移指令,可以同时修改cs:ip,也可以只修改ip;
jmp指令需要两种信息:
1】转移的目的地址
2】转移的距离
1)根据位移进行转移的jmp指令
格式:
jmp short 标号
这种格式实现的时段内转移;
对ip的修改范围是-128~127;
转移结束后cs:ip指向标号处的指令;
例如:下面的代码中 ax只会自增一次,跳过了 add ax,1;
start:mov ax,0
jmp short s
add ax,1
s:inc ax
cpu在执行jmp指令时,并不需要转移的目的地址;
例如上面的程序转换成机器码:
其中jmp short s 对应的机器码为 EB03,作用是将ip增加3;
而不是跳转到标号“s”对应的偏移地址8;
分析指令jmp short s执行过程:
1】cs:ip指向jmp short s的机器码 EB03;
2】读取EB03指令到指令缓冲器;
3】ip增加所读指令的长度,EB03的长度为2字节,因此ip=ip+2;
4】cs:ip此时指向了指令 add ax,1;也就是下一条指令;
5】指令EB03执行,ip的值增加3;此时ip=ip+2+3;cs:ip指向了inc ax,也就是标号“s”处的指令,因此add ax,1被跳过了;
通过分析可知:指令EB03并没有告诉cpu要转移的目的地址,而是告诉了cpu要转移的位移;
而这个位移是编译器根据汇编指令中的标号计算出来的;
转移位移的计算方法如图:
实际上,jmp short 标号 ,的功能是:(ip)=(ip)+8位位移;
short指明了此处的位移为8位;
8位位移范围为 -127~128;
8位位移由程序编译时算出;
例如:
jmp short s
类似的,jmp near ptr 标号,功能为:(ip)=(ip)+16位位移;
范围为 -32768~32767;
例如:
jmp near ptr s
2)转移的目的地址在指令中的jmp指令
格式:
jmp far ptr 标号
jmp far ptr 标号 ;实现的是段间转移,也叫远转移;
功能是:用标号处的cs和ip修改cs和ip的值;
例如:
start:mov ax,0
jmp far ptr s
dw 256 dup (0)
add ax,1
s:inc ax
编译后的机器码:
可以看到 jmp中同时指定了cs和ip,机器码中也包含了cs:ip的值;
3)转移的地址在寄存器中的jmp指令
指令格式:
jmp 16位寄存器
功能:
(ip)=(16位寄存器)
例如:
jmp ax
4)转移地址在内存中的jmp指令
有两种格式:
1】jmp word ptr 内存单元地址(段内转移)
功能:偏移地址(ip)=内存单元处字的值
例如:下面的代码执行完后,ip的值为123h
mov ax,123h
mov [bx],ax
jmp word ptr [bx]
2】jmp dword ptr 内存单元地址(段间转移)
功能:内存地址处有两个字,高位字存放目标段地址,低位字存放目标偏移地址;
例如:下面的代码执行完后,cs:ip的值为0:123
mov ax,123h
mov [bx],ax
mov word ptr [bx+2],0
jmp dword ptr [bx]
3.jcxz指令
jcxz是有条件转移指令;
所有有条件转移指令都是短转移;
对应的机器码中包含转移的位移,而不是地址;
对ip的修改为-128~127;
格式:
jcxz 标号
jcxz s
操作:
当寄存器cx的值为0,即(cx)=0时,转移到目标标号处;
当(cx) != 0 时,什么都不做,程序向下执行;
功能相当于if((cx) == 0) jmp short 标号;
4.loop指令
loop指令是循环指令;
所有循环指令都是短转移;
格式:
loop 标号
loop s
操作:
(cx) = (cx)-1,如果(cx) != 0转移到标号处;
如果(cx) = 0,什么都不做;
相当于(cx)--;if((cx) != 0) jmp short 标号;
5.根据位移进行转移的意义
例如:
jmp short 标号
jmp near 标号
jcxz 标号
loop 标号
这些转移指令都只包含了到目标地址ip的位移,而没包含具体目标地址;
作用:
方便了程序在内存中的浮动装配;
比如说:如果loop s 包含的是标号s的地址,那么对程序段在内存中的偏移地址有了严格的限制;
因为s处的指令如果不在目标地址处,就可能因为找不到目标指令而出错;
而包含的是位移就不存在这种问题,无论s处的指令实际地址是多少,知道了偏移量就能正确找到s处;
6.编译器对转移位移超界的检测
比如:
jmp short s 的转移范围是 -128~127;
ip最多向后移动127个字节;
如果转移范围超界,将会报错;
例如:下面的程序将报编译错误
start:jmp short s
db 128 dup (0)
s:mov ax,ffffh
7.debug专用指令
例如:直接给出目标地址的指令
jmp 2000:1
如果在汇编源程序中使用将会报编译错误;