转移指令
可以修改IP,或者同时修改CS和IP的指令统称为转移指令。换句话说转移指令就是可以控制CPU执行内存某处代码的指令。
可分为以下几类:
- 转移行为:
- 只修改IP,称为段内转移,如
jmp ax
- 同时修改CS和IP,称为段间转移,如
jmp 1000:0
- 只修改IP,称为段内转移,如
- 修改范围(段内转移):
- 短转移:修改IP范围-128~127
- 近转移:修改IP范围-32768~32767
- 转移指令分类:
codesg segment start: mov ax,offset start ;相当于mov ax,0 s: mov ax,offset s ;相当于mov ax,3 codesg ends
end start
;因为第一条指令的长度为3,所以标号start的偏移地址为0,标号s的偏移地址为3
这里就是将start和s的偏移地址分别送给ax,也就是0和3
<a name="eKmWY"></a>
## jmp指令
jmp是无条件转移指令,可以只修改IP也可以同时修改CS和IP,只要给出两种信息,要转移的目的地址和专一的距离。
依据位移的jmp指令:`jmp short 标号`(转到标号处执行指令)。这个指令实现的是段内短转移,对IP修改范围是-128~127,指令结束后CS:IP指向标号的地址,如:
0BBD:0000 start:mov ax,0 (B80000) 0BBD:0003 jmp short s (EB03) 0BBD:0005 add ax,1 (050100) 0BBD:0008 s:inc ax (40)
执行之后ax值为1,因为跳过了add指令。
还应注意的是,jmp short短转移指令并不会在机器码中直接写明需要转移的地址(0BBD:0008),jmp的机器码是EB03并没有包含转移的地址,这里的转移距离是相对计算而出的地址,来看下面的执行过程:
1. (CS)=0BBDH,(IP)=0006H,CS:IP指向EB03(jmp short s)
1. 读取指令EB03进入指令缓冲器
1. (IP)=(IP)+指令长度,即(IP)=(IP)+2=0008H,之后CS:IP指向add ax,1
1. CPU指向指令缓冲器中的指令EB03
1. 执行之后(IP)=000BH,指向inc ax
在`jmp short s`的机器码中,包含的并不是转移的地址,而是转移的位移,这里的位移是相对计算出来的,用8位一字节来表示,所以表示范围是-128~127,用补码表示。计算方法如是,8位位移=标号处地址-jmp下一条指令的地址。当然还有一种类似的指令是`jmp near ptr 标号`,是近转移,原理一样,只是表示位移的是字类型16位,表示范围-32768~32767。
<a name="LU57z"></a>
## jmp+地址远转移
`jmp far ptr 标号`实现的是段间转移,也就是远转移,它的机器码中指明了转移的目的地址的CS和IP的值,如下面例子:
0BBD:0000 start:mov ax,0 (B80000)
0BBD:0003 mov bx,0 (BB0000)
0BBD:0006 jmp far ptr s (EA0B01BD0B)
0BBD:000B db 256 dup (0)
0BBD:010B s:add ax,1
0BBD:010X inc ax
```
可以看出,jmp的机器码中明确指明了跳转位置s的地址0BBD:010B,在低位的是IP的值,高位的是CS的值。
jmp+寄存器|内存转移
jmp 寄存器
:jmp 16位reg
,实现的是(IP)=(16位reg),之前讨论过,直接修改IP的值为寄存器中的值。jmp 内存
:jmp加内存使用的时候有两种用法:
jmp word ptr
内存单元地址(段内转移)- 从内存单元地址处开始存放一个座位转移目的的偏移地址的字
- 内存单元支持任何寻址方式
- 如
jmp word ptr ds:[0]
,执行后(IP)=0123H(ds:[0]中的值是123H)
jmp dword ptr 内存单元地址
(段间转移)- 从内存单元地址处开始存放两个字,高位存放段地址,低位偏移地址作为转移的目的地址
- (CS)=(内存单元地址+2),(IP)=(内存单元地址),支持任一种寻址方式
- 如
jmp dword ptr [bx]
跳转到0:123Hjcxz指令
jcxz指令为条件转移指令,所有的条件转移指令都是短转移,转移范围是-128~127,机器码中包含的是ip的位移而不是目的地址。使用格式是jcxz 标号
,功能是如果(cx)=0则跳转到标号处执行;如果(cx)!=0,那么什么也不做继续执行代码。loop指令
loop为循环指令,所有的循环指令都是短转移,转移范围是-128~127。使用格式是loop 标号,功能是如果(cx)!=0那么跳转到标号处执行;如果(cx)=0那么什么也不做继续执行程序。根据位移进行转移的指令总结
下面几条指令是根据位移进行转移(相对计算转移位置,而不是直接提供转移目的的IP和CS的值)
jmp short 标号
jmp near ptr 标号
jcxz 标号
loop 标号
这些指令之所以是间接计算标号的位置,是为了方便在代码中浮动装配,使得循环体或这些指令的代码段在任何位置都可以执行(不要超跳转范围)。而编译器会对跳转的范围进行检测,如果跳转超过了范围,编译器会报错。
注:jmp 2100:0
是debug使用的汇编指令,编译器并不认识。