1.5_汇编(转移指令的原理)

前言

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

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

  1. 段间转移和段内转移
    段内转移分两种:短转移和近转移`

常用的转移指令

操作符offset

操作符offset在汇编语言中是由编译器处理的符号,它的功能是取得标号的偏移地址。
给出下列程序段,填写两条指令,使该程序在运行中将s处的一条指令复制到s0处。

1
2
3
4
5
6
7
8
9
10
11
assume  cs:codesg  
codesg segment
s: mov ax,bx
mov si,offset s
mov di,offset s0
__________
__________
s0: nop
nop
codesg ends
end s

提出以下几个问题:

  1. s和s0处的指令所在的内存单元的地址是多少?
  2. 将s处的指令复制到s0处,如何进行操作?
  3. 段地址已知在cs中,偏移地址offset s和offset s0已经送入si和di中。
  4. 要复制的数据有多长?

思考所得:

  1. 通过“offset 标号”可以得到标号的地址;
  2. 在8086CPU中,得到的标号地址是八位数据。

jmp指令

  1. 根据位移进行转移的jmp指令
    jmp short 标号(转到标号处执行指令)
    这种情况下执行的jmp指令在机器指令里的跳转数据并不是目标程序(或标号)的地址,而是相对偏移地址,比如jmp的前一句指令的地址为a,跳转的目标指令的地址为b,在机器指令里,只出现b-a的值,并不直接指明地址b。
    这说明,CPU在执行jmp指令的时候并不需要转移的目的地址
  2. 转移的目的地址在指令中的jmp指令
    jmp far ptr 标号
    上述指令实现的是段间转移,又称为远转移。可以同时修改CS和IP。
  3. 转移地址在寄存器中的jmp指令
    指令格式:jmp 16位reg
    这种修改方式只能修改IP,并不能修改CS
  4. 转移地址在内存中的jmp指令
    a、jmp word ptr 内存单元地址(段内转移)
    在内存单元地址处开始存放着一个字
    b、jmp dword ptr 内存单元地址(段间转移)
    在内存单元地址处开始存放着两个字

我是否可以这么理解?当我提供给jmp16位数据时,只进行IP的修改,即进行段内转移,
当你提供给它32位数据时,它填满了IP,即会填充CS,实现段间转移。

jcxz条件转移指令

jcxz 标号(如果(cx)==0,转移到标号处执行)

loop指令

loop指令为循环指令,所有的循环指令都是“短转移”,在对应的机器码中包含转移的位移,而不是目的地址。对IP的修改范围为:-128~127。


转移指令背后的思考

根据位移进行转移的意义

采用这种位移的设计,方便了程序段在内存中的浮动装配。
如下程序所示:

1
2
3
4
    mov cx,6    B9 06 00 
mo ax,10h B8 10 00
s: add ax,ax 01 C0
loop s E2 FC ;前移了4个字节

这样的程序装在内存的不同位置都可正确执行。

编译器对转移位移超界的检测

看如下代码:

1
2
3
start:  jmp short s
db 128 dup(0)
s: mov ax,offffh

假设程序的入口在start处,那么在进行编译的时候,jmp指令标号s中间存在128字节的距离,而jmp short s的转移范围是-128~127,只能向后跳转127个字节,所以会编译报错。


后记

通过对CPU工作原理的深入学习,实现在底层上真正的自由。


——《编程语言》 王爽 著