zoukankan      html  css  js  c++  java
  • 汇编09:转移指令的原理

    转移指令的原理

    可以修改IP,或同时修改CS和IP的指令统称为转移指令。

    转移行为有很多种不同的分类方法:

    根据只修改IP和同时修改CS和IP,可以分为段内转移(jmp ax)和段间转移(jmp 1000:0)

    根据指令对IP的修改范围不同,段内转移又分为短转移(IP的修改范围为-128-127)和近转移(IP的修改范围-32768-32767)

    8086CPU的转移指令分为以下几类:

    1、无条件转移指令,如jmp

    2、条件转移指令

    3、循环指令,如loop

    4、过程

    5、中断

    操作符offset

    offset是一个伪指令,它的功能是取得标号的偏移地址,如:

    assume cs:codesg
    codesg segment
    	start:	mov ax,offset start
    	s:	mov ax,offset s
    codesg ends
    end start
    

    第三行语句中的offset start就相当于0,因为start标号的偏移地址为0;第四句中的offset s就相当于3,因为s标号的偏移地址为3,这是由于第一条指令长度为3个字节。

    有了offset我们就可以方便的取到标号的偏移地址了,我们可以先设置一个标号中放入nop(占1个字节的机器码):

    s0:	nop
    	nop
    

    然后再将其他标号s处的指令直接复制过去:

    mov si,offset s
    mov di,offset s0
    mov ax,cs:[si]
    mov cs:[di],ax
    

    jmp指令

    jmp为无条件转移指令,它要给出两种信息:要转移的目的地址,或者要转移的距离。

    转到标号处执行指令

    使用格式:

    jmp short 标号
    

    它实现的是段内短转移,对IP的修改范围为-128-127,也就是说它向前转移时最多可以越过128个字节,向后转移时可以最多越过127个字节,转移指令结束后,CS:IP应该指向标号处的指令。

    值得注意的是,这个指令对应的机器码中是没有转移的目的地址的,而是包含转移的位移,编译器根据两点的距离计算出位移量,然后修改IP寄存器中的值,在编译结束后的机器指令中就包含转移位移了。相当于该指令的作用其实是(IP)=(IP)+8位位移。

    对应的段内近转移指令:

    jmp near ptr 标号
    

    他对IP的修改范围为-32768-32767.相当于(IP)=(IP)+16位位移。

    对应的远转移指令(段间转移):

    jmp far ptr 标号
    

    这个指令对应的机器码中就包含了转移的目的地址了。

    使用内存地址和寄存器

    jmp可以直接加16位reg:

    jmp 16位reg
    

    它的意思就是修改IP寄存器的值,修改为对应寄存器中的值。

    jmp命令中也可以直接包含地址,它有两种形式:

    1、只修改IP的段内转移:

    jmp word ptr ds:[0]
    

    相当于把对应地址的值赋值给IP寄存器,完成转移。

    2、同时修改IP和CS的段间转移:

    jmp dword ptr ds:[0]
    

    从对应内存地址单元中取出两个字,低地址的那个字赋值给IP,高地址的那个字赋值给CS,完成转移。

    jcxz指令

    jcxz为有条件转移指令,所有的有条件转移指令都是短转移,在对应的机器码中包含转移的位移,而不是目的地址。对IP的修改都是-128-127.

    使用格式:

    jcxz 标号
    

    相当于如果cx寄存器中的值是0,就执行:

    jmp short 标号
    

    loop指令

    loop指令是循环指令,所有的循环指令都是短转移,基本使用用法:

    loop 标号
    

    相当于:

    (cx)--
    if((cx)!=0)jmp short 标号
    

    关于转移位移的讨论

    在上述段内转移指令中,我们可以发现这些指令对应的机器码中只有转移的相对位移,而不包含转移的目的地址,这种设计是为了方便程序段在内存中的浮动装配。

    如果我们自定义的程序要直接引用某个写好的目标文件,这个文件内部的转移写成段内转移,这样就可以保证在连接时不会出错,不会因为该目的地址有其他内容而覆盖。

    此外还要注意位移超界的问题,如果转移范围出现超界,编译器会报错。

  • 相关阅读:
    angular2
    angular1
    JavaScript随笔1
    鼠标样式
    清除浮动
    css-父标签中的子标签默认位置
    [Leetcode] Decode Ways
    [Java] 利用LinkedHashMap来实现LRU Cache
    LinkedHashMap和HashMap的比较使用(转)
    [Java] java.util.Arrays 中使用的 sort 采用的算法 (转)
  • 原文地址:https://www.cnblogs.com/yinyunmoyi/p/12811516.html
Copyright © 2011-2022 走看看