经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » 汇编语言 » 查看文章
汇编学习笔记之转移指令
来源:cnblogs  作者:迷茫的蕉太狼  时间:2021/6/15 9:14:36  对本文有异议
  1. 什么是转移指令:

可以修改IP,或同时修改CS和IP的指令统称为转移指令。转移指令可以通过修改CS和IP的值来实现对CPU执行内存某处代码的控制

  1. 段内转移:指令转移方式IP=IP+位移。等同于JMP 当前IP+需要位移字节

    段内转移只修改IP,还是处于一个CS段地址内,例如:JMP AX

    1. 段内短转移JMP SHORT 标号

      段内短转移,位移为8bit位,最高位为符号位。剩余7个bit位可位移,位移间距是:-128~127,也就是说在编译之后,使用JMP SHORT 标号指令往前转移最多128个字节,往后转移最多127个字节。

      代码示例:

      1. ASSUME CS:CODE
      2. CODE SEGMENT
      3. START:
      4. MOV AX,0
      5. MOV BX,0
      6. JMP SHORT S
      7. ADD AX,1 ; 机器码:B80100
      8. ADD AX,3 ; 机器码:B80300
      9. DB 121 DUP(0)
      10. S:
      11. INC AX
      12. CODE ENDS
      13. END START

      编译后的机器码为121个00字节的机器码。121+3(B80100)+3(B80300)=127个字节,如果将DB 121 DUP(0)改成DB 122 DUP(0),那么程序在MASM 编译时期就无法通过,因为129个字节已经完全超过了8位bit。不信的话可以试试

    2. 段内近转移:JMP NEAR PTR 标号

      段内近转移,位移为16个bit位,最高位为符号bit位,剩余15个bit为可进行位移,位移间距是-32768~32767,在编译之后,使用JMP NEAR PTR 标号转移指令至多往前转移32768个字节,往后至多转移32767字节。

      代码示例:

      1. ASSUME CS:CODE
      2. CODE SEGMENT
      3. START:
      4. MOV AX,0
      5. MOV BX,0
      6. JMP NEAR PTR S
      7. ADD AX,2
      8. DB 128 DUP(0)
      9. S:
      10. INC AX
      11. CODE ENDS
      12. END START

      JMP NEAR PTR 标号编译后的机器码为E90000。后面四位就是位移范围,低位在前,高位在后。用法与JMP SHORT基本一致,只不过前者适用于需要更大幅度的单元跳转的场景

    3. 为啥近转移比短转移多了个PTR关键字?

      这是网上搜索到的一句话:汇编里面 ptr 是规定 的 字 (既保留字),是用来临时指定类型的

  2. 段间转移:JMP FAR PTR 标号

    段间转移,同时修改CS和IP的值,可跨越不同段直接进行指令转移。等同于JMP CS:IP。同时CS=标号所在段地址,IP=标号所在段地址偏移量。也就是说最大转移幅度应该是(cs*10H)+IP=FFFFF。相当于20个bit位进行位移。最大幅度应该是-1,048,576~1,048,575个字节。

  3. 使用内存单元进行指令转移

    1. 使用内存单元进行近转移:JMP WORD PTR 内存单元地址

      从内存单元地址处开始存放着一个字,是转移目的地指令的偏移地址。

      偏移地址计算方式:JMP DS:[BX]。将BX指向的内存单元中的数据用于IP寄存器的值。跳转到指定的位置。偏移量范围参考:段内近转移

    2. 使用内存单元进行段间转移:JMP DWORD PTR 内存单元地址

  4. 有条件转移

    所有有条件转移指令都是短转移,在对应的机器码中包含转移的位移,而不是目的地址。对IP的修改范围参考段内短转移

    1. JCXZ 指令

      JCXZ 标号为有条件转移指令之一,它用于判断CX是否等于0,如果等于0,则执行指令转移,否则它什么都不做,程序继续往下执行,用Java语言的语法表示为:if(cx == 0){jmp ip}。这样举例或许更好理解JCXZ指令的作用

      代码示例:

      1. ASSUME CS:CODE,DS:DATA
      2. CODE SEGMENT
      3. START:
      4. MOV AX,DATA
      5. MOV DS,AX
      6. MOV AX,0
      7. MOV BX,0
      8. S:
      9. MOV CL,DS:[BX] ; 将内存单元中的值取出,保存到CL
      10. JCXZ SAVE ; 如果CX==0时,转移到SAVA标号处,保存当前BX的偏移量
      11. INC BX ; 如果CX!=0时,BX+1,也就是偏移量+1。继续转移到S标号处执行
      12. JMP SHORT S
      13. SAVE:
      14. MOV DX,BX
      15. MOV AH,4CH
      16. INT 21H
      17. CODE ENDS
      18. DATA SEGMENT
      19. DB 12,20,32,00,36
      20. DATA ENDS
      21. END START
    2. LOOP 指令

      LOOP 标号是一个循环指令,但是也是属于有条件转移指令的一种。需要注意的是所有循环指令都是短转移。它判断CX中的值,是否需要进行指令转移。跟JCXZ指令恰恰相反,LOOP指令用判断CX-1之后是否不等于0,如果不等于0则转移到标号处。如果等于0,则程序往下执行。用Java语言表示的话,应该是下面代码所执行的效果,其中while就相当于LOOP指令,每次指令LOOP指令转移时,先将CX中的值-1,然后在判断CX不等于0

      Assembly代码:

      1. ASSUME CS:CODE
      2. CODE SEGMENT
      3. MOV CX,32
      4. S:
      5. ; LOOP循环体代码段,这里只能有125个字节哦
      6. LOOP S
      7. COED ENDS

      Java代码:

      1. public class Test{
      2. public static void main(String[] args){
      3. int cx = 32;
      4. while((--c) != 0){
      5. // 标号处到LOOP指令之间的代码段
      6. }
      7. }
      8. }

    以上举的两个例子都是使用CX寄存器是否为0进行条件判断的。还有使用标志寄存器作为条件进行指令转移的指令,详情查看:《条件转移指令之使用标志寄存器进行指令转移》

原文链接:http://www.cnblogs.com/arblogs/p/14866234.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号