若余相思 发表于 2017-9-17 18:15:43

第九章 转移指令的原理

前言
        可以修改IP,或同时修改CS和IP的指令统称为转移指令。转移指令能够控制CPU执行某处的代码的指令。
        8086CPU的转移分如下几类:
1、只能修改IP的称为段内转移, 如:jmp ax
2、同时修改CS和IP称为段间转移,如:jmp dword ptr 内存地址   注意:jmp 1000:0这个指令只能在debug中使用

由于段内转移对修改的范围不同,又有段转移和近转移。
1、段转移:修改范围是 -128~127
2、近转移:修改范围是 -32768~32767

8086CPU的转移指令又分一下几类:
1、无条件转移,如:jmp
2、条件转移,如:jcxz
3、循环指令,如;loop
4、过程
5、中断


9.1节操作符offset

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

code segment

start : mov ax, offset start;相当于mov ax, 0
        s :        mov ax, offset s           ;相当于mov ax, 3
       
code ends
end start

问题:在如下程序添加两条指令,使该程序在运行中将s处的一条指令复制到s0处。
代码如下:
assume cs: code

code segment

start : mov ax, bx    ;此行代码占2个字节的机器码
                mov si, offset start
                mov di, offset s
               
                mov ax, cs:
                mov cs:, ax
               
        s : nop
                nop
               
code ends
end start

其实就是将s处的机器码放在ax中,然后再将ax中的内容放在s0中

9.3节根据位移进行转移的jmp指令
        jmp short 标号(转到标号处进行执行),这种格式进行段内短转移,范围是-128~127
如:
assume cs: code

code segment

start : mov ax, 0
                jmp short s
                add ax, 1
        s : inc ax
       
code ends
end start

执行后ax = 1,因为它没有执行add ax, 1直接jmp到inc ax中执行。

重点来了:CPU执行jmp指令时并不需要转移的目的地址,只需要8位的位移 = 标号处的地址 - jmp指令后的第一个字节的地址,这个会在jmp指令的机器码中的,用补码表示

实际上:jmp short 标号的功能为:(IP) = (IP) + 8位位移
(1)8位的位移 = 标号处的地址 - jmp指令后的第一个字节的地址;
(2)short指明此处的位移为8位位移
(3)8位位移的范围为-128~127,用补码表示
(4)8位位移由编译程序在编译时算出

“jmp near ptr 标号”的功能为:(IP) = (IP) + 16位位移
(1)16位的位移 = 标号处的地址 - jmp指令后的第一个字节的地址;
(2)near ptr指明此处的位移为16位位移
(3)16位位移的范围为-32768~32767,用补码表示
(4)16位位移由编译程序在编译时算出


        “jmp far ptr 标号”为段间转移,又称远转移。功能:(CS) = 标号所在的段地址, (IP) = 标号所在段中的偏移地址。
        far ptr指明了用标号的段地址和偏移地址修改了CS和IP

程序:
assume cs: code

code segment

start : mov ax, 0
                mov bx, 0
                jmp far ptr s
                db 256 dup (0)
        s : add ax, 1
                inc ax
       
code ends
end start

这个程序的机器码是:


可以看到jmp far ptrs所在的机器码为:EA 0B 01 BD 0B 可知转移的段地址为:DBBDH,转移的偏移地址为010BH

        转移地址在寄存器的jmp指令:jmp 16位reg,功能:(IP) = (16位reg)

9.6节转移地址在内存在的jmp指令

        (1)jmp word ptr 内存单元地址(段内转移)

如: mov ax, 0123H
        mov ds:, ax
        jmp word ptr ds:

        执行后(IP) = 0123H

        (2)jmp dword ptr 内存单元地址(段间转移)

        功能:从内存单元地址开始处放着两个字,高地址的字是转移的目的的段地址,低地址处的是转移的目的的偏移地址,
        (CS) = (内存单元地址 + 2)
        (IP) = (内存单元地址)

        mov ax , 0123H
        mov ds, ax
        mov bx, 0
        mov word ptr ds:2, 0
        jmp dword ptr ds:

        执行后,(CS) = 0, (IP) = 0123H,CS:IP指向0000:0123

9.7 节jcxz 指令

        指令格式:jcxz 标号 (如果cx为0,转移到标号处执行)
操作:当(cx) = 0时,(IP) = (IP) + 8位位移
(1)8位的位移 = 标号处的地址 - jcxz指令后的第一个字节的地址;
(2)8位位移的范围为-128~127,用补码表示
(3)8位位移由编译程序在编译时算出

用C语言描述为 if (cx == 0) { jmp short 标号}

9.8 节 loop 指令

        指令格式:loop 标号((CX) = (CX) - 1, 如果CX不为0,则转移到标号处执行)
操作:
(1)(cx) = (cx) - 1;
(2)如果cx不为0,则转移到标号处执行

C语言描述为;
(cx) --;
if (cx != 0) {jmp short 标号}

总结

(1)操作符offset功能是取得标号处的偏移地址,由编译器操作
(2)jmp short 标号、jmp near ptr 标号称为段内转移,范围分别是-128~127和-32768~32767
(3)jmp far ptr 标号表示段间转移,CS为标号所在的段地址,IP为标号所在的偏移地址
(4)jmp word ptr 内存单元只能修改IP,而jmp dword ptr 内存单元能修改CS和IP, CS在[内存单元 + 2]        ,IP在[内存单元]中,高地址存放在CS中,低地址在IP中
(5)还有jcxz指令,cx为0时就转移到jcxz 标号处,还有熟悉的loop指令
(6)还有就是重点的是:转移指令不存放转移的目的地址,只存放标号所在的地址 - jmp指令后面的地址
页: [1]
查看完整版本: 第九章 转移指令的原理