在雨一方

万里寻山历百艰而无悔,一朝见井纵九死以何辞。

转移指令的原理
    可以修改IP,或同时修改CS和IP的指令统称为转移指令。概括来讲,转移指令就是可以控制CPU执行内存中
某处代码的指令。

    8086CPU的转移指令有以下几类。
        (1)只修改IP时,称为段内转移,比如:jmp ax。
        (2)同时修改CS和IP时,称为段间转移,比如:jmp 1000:0

    由于转移指令对IP的修改范围不同,段内转移又分为:短转移和近转移。
        (1)短转移IP的修改范围为-128~127.
        (2)近转移IP的修改范围为—32768~32767.

    8086CPU的转移指令分为以下几类。
        (1)无条件转移指令(如:jmp)
        (2)条件转移指令。
        (3)循环指令(如:loop)
        (4)过程
        (5)中断

jmp指令

    jmp为无条件转移指令,可以只修改IP,也可以同时修改CS和IP。

    jmp指令要求给出两种信息:
        (1)转移的目的地址
        (2)转移的距离(段间转移,段内短转移,短内近转移)

    jmp short 标号
    转到标号处执行指令,这种格式的jmp指令实现的时段内短转移,他对IP的修改范围为
—128~127,“short”标号说明指令进行的时短转移。

    汇编指令中的idata(立即数),不论它是表示一个数据还是内存单元的偏移地址,都会在对应的机器指令
中出现,因为CPU执行的时机器指令,他必须要处理这些数据或地址。

(https://img-blog.csdn.net/20160611135522461)

    由图中jmp 0008的机器码可知,cpu在执行jmp指令的时候并不需要转移的目的地址。实际上jmp在机器码
中并未给出转移的目的地址,而是给出了转移的位移。jmp 0008这条指令要使(IP)=0008H,而当前的(IP)
=0005H,而当前IP加0003H正好为目的地址。

    ps:
        为什么会说当前(IP)为0005H而不是0003H呢.
        因为CPU执行指令的步骤如下
        (1)从CS:IP指向内存单元读取指令,读取的指令进入指令缓冲区。
        (2)(IP)=(IP)+所读取指令的长度,从而指向下一条指令。
        (3)执行指令。转到1,重复执行这个过程。
        实际上我们是先增加了当前(IP)之后才执行指令,所以在执行指令时的当前(IP)是下一条指令的
    开始处的(IP)。

    实际上“jmp short 标号”的功能是:(IP)=(IP)+8位位移(8位位移=标号出地址-jmp指令后的第一个
字节的地址,这8位位移由编译程序在编译时算出)。

    而“jmp near ptr标号”的功能为:(IP)=(IP)+16位位移(其它情况同上)。

    前面两个均是段内转移,且对应的机器指令中并没有转移的目的地址,而是相对于当前IP的转移地址,
而“jmp far ptr 标号”实现的是段间转移,又称为远转移。far ptr指明了指令用标号的段地址和偏移地址修
改CS和IP。
    eg:
        assume cs:code
        code segment
         start:
             mov ax,0
             mov bx,0
             jmp far ptr s  ;CS:IP为0BBD:0006 机器指令为:EA0B01BD0B
             db 256 dup (0)
         s:
             add ax,1 ;s对应的CS:IP为0BBD:010B
             inc ax
        code ends
        end start
    由上可之,段间转移会给出转移的目的地址,而不同段内转移给出的转移位移。

转移地址在寄存器中的jmp指令

    指令格式:jmp 16位reg
    功能:(IP)=(16位reg)

转移地址在内存中的jmp指令

    (1)jmp word ptr 内存单元地址(段内转移)
        功能:从内存单元地址开始存放着一个字,是转移的目的偏移地址(内存单元地址可用寻址的任意一
    种格式给出)。
        eg:
            mov ax.0123H
            mov [bx],ax
            jmp word ptr [bx]
            执行后,(IP)=0123H

    (2)jmp dword ptr 内存单元地址(段间转移)
        功能:
        从内存单元地址处开始存放着两个字,高地址处的字是转移的目的段地址,低地址处是转移的目的偏移
    地址。
        (CS)=(内存单元地址+2)
        (IP)=(内存单元地址)
        eg:
            mov ax,0123H
            mov [bx],ax
            mov word ptr [bx+2],0
            jmp dword ptr [bx]
            执行后,(CS)=0,(IP)=0123H,CS:IP指向0000:0123

汇编编译器(masm.exe)对jmp的相关处理

    1.向前转移
        编译器中有一个地址计数器(AC),编译器在编译过程中,每读到一个字节AC就加1。再向前转移时,
    编译器可以在读到标号s后记下AC的值as,在读到jmp s后记下AC的值aj。编译器用as-aj算出位移disp。

        (1)如果disp为[-128,127],则不管汇编指令是:
            jmp s
            jmp short s
            jmp near ptr s
            jmp far ptr s
中的哪一种,都将其转换为jmp short s对应的机器码(EB disp)。

        (2)如果disp为[-32768,32767],则:
            对于jmp short s将产生编译错误。
            对于jmp s,jmp near ptr s将产生jmp near ptr s对应的机器码(E9 disp)。
            对于jmp far ptr s将产生相应的编码,jmp far ptr s所对应的机器码格式为:
EA 偏移地址 段地址。

2.向后转移
        在向后转移的情况下,编译器先读到jmp s指令。由于它还没有读到标号s,所以编译器此时还不能确
    定标号s处的AC值。也就是说,编译器不能确定位移量disp的大小。

        此时,编译器将jmp s指令都当作jmp short s来读取,记下jmp s指令的位置和AC的值aj,并作如下
    处理:

        对于jmp short s,编译器生成EB和1个nop指令(相当于预留一个字节的空间,存放8位的disp)。

        对于jmp s和jmp near ptr s,编译器生成EB和2个nop指令(相当于预留两个字节的空间,存放16
    位的disp)。

        对于jmp far ptr s,编译器生成EB和4个nop指令(相当于预留4个字节的空间,存放16位的
    disp)。

        做完上述处理后,编译器继续运行,当向后读到标号s时,记下AC的值as,并计算出转移的位移量:
    disp=as-aj。
阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

不良信息举报

转移指令的原理

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭