转移指令

可以修改IP,或者同时修改CS和IP的指令统称为转移指令。换句话说转移指令就是可以控制CPU执行内存某处代码的指令。

可分为以下几类:

  • 转移行为:
    • 只修改IP,称为段内转移,如jmp ax
    • 同时修改CS和IP,称为段间转移,如jmp 1000:0
  • 修改范围(段内转移):
    • 短转移:修改IP范围-128~127
    • 近转移:修改IP范围-32768~32767
  • 转移指令分类:
    • 无条件转移:jmp
    • 条件转移
    • 循环指令
    • 过程
    • 中断

      offset操作符

      offset操作符在汇编语言中时由编译器处理的符号,它的功能是取得标号地偏移地址。如: ``` assume cs:codesg

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

  1. 这里就是将starts的偏移地址分别送给ax,也就是03
  2. <a name="eKmWY"></a>
  3. ## jmp指令
  4. jmp是无条件转移指令,可以只修改IP也可以同时修改CSIP,只要给出两种信息,要转移的目的地址和专一的距离。
  5. 依据位移的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)

  1. 执行之后ax值为1,因为跳过了add指令。
  2. 还应注意的是,jmp short短转移指令并不会在机器码中直接写明需要转移的地址(0BBD:0008),jmp的机器码是EB03并没有包含转移的地址,这里的转移距离是相对计算而出的地址,来看下面的执行过程:
  3. 1. (CS)=0BBDH,(IP)=0006HCS:IP指向EB03jmp short s
  4. 1. 读取指令EB03进入指令缓冲器
  5. 1. (IP)=(IP)+指令长度,即(IP)=(IP)+2=0008H,之后CS:IP指向add ax,1
  6. 1. CPU指向指令缓冲器中的指令EB03
  7. 1. 执行之后(IP)=000BH,指向inc ax
  8. `jmp short s`的机器码中,包含的并不是转移的地址,而是转移的位移,这里的位移是相对计算出来的,用8位一字节来表示,所以表示范围是-128~127,用补码表示。计算方法如是,8位位移=标号处地址-jmp下一条指令的地址。当然还有一种类似的指令是`jmp near ptr 标号`,是近转移,原理一样,只是表示位移的是字类型16位,表示范围-32768~32767
  9. <a name="LU57z"></a>
  10. ## jmp+地址远转移
  11. `jmp far ptr 标号`实现的是段间转移,也就是远转移,它的机器码中指明了转移的目的地址的CSIP的值,如下面例子:

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:123H

      jcxz指令

      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使用的汇编指令,编译器并不认识。