9.《汇编语言》-王爽第三版学习笔记 转移指令的原理

1.可以修改 IP, 或通知修改 CS 和 IP 的指令 统称为 转移指令。

概括的讲,转移指令就是可以控制 CPU 执行内存中某处代码的指令。

8086CPU 的转移行为有一下几类:

  • 只修改 IP 时, 称为段内转移, 比如: jmp ax
  • 同时修改 CS 和 IP 时,称为段间转移,比如: jmp 1000:0

由于转移指令对 IP 的修改范围不同,段内转移又分为: 短转移 和 近转移

  • 短转移 IP 的修改范围为 -128~127
  • 近转移 IP 的修改范围 -3287~32767

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

  • 无条件转移指令(如: jmp)
  • 条件转移指令
  • 循环指令(如:loop)
  • 过程
  • 中断

2. 操作符 offset

offset在汇编语言中是由编译器处理的符号。他的功能是 取得标号的偏移地址。

// 将 start 处的第一条指令 复制到 s0处:
assume cs:codesg
codesg segment
start: mov ax,bx 
         mov si,offset start  // 相当于 mov si,0
         mov di,offset s0  // 相当于 mov di, s0代码段的首地址
         mov ax,cs:[si] 
         mov cs:[di],ax
   s0: nop       // nop的机器码占一个字节
         nop

       mov ax,4c00H
       int 21H
codesg ends
end start

3. jmp 指令

jmp 指令 为 无条件转移指令,可以只修改 IP,也可以同时修改 CS 和 IP。需要给出两种信息:
(1)转移的目的地址
(2)转移的距离(段间转移,段内短转移,段内近转移)

3. 依据位移进行转移的 jmp 指令

jmp short 标号 (转移到标号处执行指令)
这种格式的 jmp 指令实现的是 段内短转移,它对 IP 的修改范围为 -128~127,也就是说,它向前转移时最多越过 128 个字节,向后转移可以最多越过 127 个字节。
jmp指令中的"标号" 是 代码段中的标号, 指明了指令要转移的目的地,转移指令结束后, CS:IP 应该指向标号处的指令。

9B6875FF-4A69-419B-9720-5577A42FED9B.png

CPU在执行 jmp 指令的时候并不需要转移的目的地址。
”jmp short 标号“ 指令所对应的机器码中,并不包含转移目的地的地址,而是包含转移的位移。这个位移 是编译器根据汇编指令中的 ”标号“ 计算出来的。

413F34DB-4766-4814-A820-4C86EEDEC68E.png

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

  • 实际上 ”jmp near ptr 标号“ 的功能为: (IP) = (IP)+16位位移
    (1) 16位位移 = 标号处的地址 - jump 指令后第一个字节的地址
    (2)near ptr 指明此处的位移位 16位位移, 进行的是段内近转移。
    (3)16位位移的范围为 -32768~32787,用补码表示。
    (4)16位位移由编译程序在编译时算出。

  • 实际上 ”jmp far ptr 标号“ 的功能为: 段间转移,又称远转移
    far ptr 指明了用 标号的段地址 和 偏移地址 修改 CS 和 IP。
    (1) 16位位移 = 标号处的地址 - jump 指令后第一个字节的地址
    (2)near ptr 指明此处的位移位 16位位移, 进行的是段内近转移。
    (3)16位位移的范围为 -32768~32787,用补码表示。
    (4)16位位移由编译程序在编译时算出。


    F220E338-FF2C-4744-95DF-5CF4769EA72E.png
  • ”jump16位 reg“ 的功能为: (IP)=(16位reg)
    far ptr 指明了用 标号的段地址 和 偏移地址 修改 CS 和 IP。
    (1) 16位位移 = 标号处的地址 - jump 指令后第一个字节的地址
    (2)near ptr 指明此处的位移位 16位位移, 进行的是段内近转移。
    (3)16位位移的范围为 -32768~32787,用补码表示。

  • ”jmp word ptr 内存单元地址“ 的功能为: 段内转移
    从内存单元地址处开始存放着一个字,是转移的目的偏移地址。

  • ”jmp dword ptr 内存单元地址“ 的功能为: 段间转移
    从内存单元地址处开始存放着两个字,高地址处的字是转移的目的段地址, 低地址出是转移的目的偏移地址。
    (CS)= (内存单元地址+2)
    (IP)=(内存单元地址)

4. 练习

1.若要使程序中的jmp指令执行后,CS:IP指向程序的第一条指令,在data段中应该定义哪些数据?

assume ds:data,cs:code
data segment
    db 2 dup (0)
data ends
code segment
start: mov ax,data
       mov ds,ax
       mov bx,0
       jmp word ptr [bx+1]
       mov ax,4c00h
       int 21h
code ends
end start

2.补全程序,使得jmp指令执行后,CS:IP指向第一条指令

assume ds:data,cs:code
data segment
    dd 12345678H
data ends
code segment
start: mov ax,data
       mov ds,ax
       mov bx,0
       mov [bx],bx
       mov [bx+2],code
       jmp dword ptr ds:[0]
       mov ax,4c00h
       int 21h
code ends
end start

3.;内存数据如下
2000:1000 BE 00 06 00 00 00 ……
此时CPU执行指令
mov ax, 2000H
mov es, ax
jmp dword ptr es:[1000H]
 
后,(CS) = 0006H (IP) = 00BEH

5. jcxz 指令

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

  • 当 (cx)!= 0 时,什么也不做,程序继续执行
  • jcxz 标号 = if (cx) == 0 jump short 标号

6. 练习

补全编程,利用jcxz指令,实现在内存2000H段中查找第一个值为0的字节,找到后,将它的偏移地址存储在dx中。

assume cs:code

code segment

start: mov ax,2000H
       mov ds,ax
       mov bx,0

    s: mov cl,[bx]
       mov ch,0
       jcxz ok
       inc bx
       jmp short s

   ok: mov dx,bx
       mov ax,4c00h
       int 21h

code ends

end start

7. loop 指令

指令格式:loop 标号
操作:
(1)(cx)= (cx)+ 1
(2)如果(cx)!= 0, (IP)=(IP)+8 位位移

8. 练习

补全编程,利用loop指令,实现在内存2000H段中查找第一个值为0的字节,找到后,将它的偏移地址存储在dx中。

assume cs:code

code segment

start: mov ax,2000H
       mov ds,ax
       mov bx,0

    s: mov cl,[bx]
       mov ch,0
       inc cx
       inc bx
       loop s

   ok: dec bx
       mov dx,bx
       mov ax,4c00h
       int 21h

code ends

end start

9. 根据位移进行转移的意义

jmp short 标号
jmp near ptr 标号
jcxz 标号
loop 标号
他们对IP的修改是根据 转移目的地址和转移起始地址之间的位移来进行。在它们对应的机器码中不包含转移的目的地址,而包含的是目的地之的位移。方便了程序段在内存中的浮动装备,无论目的地址如何变化,指令的转移位移是不变的。

你可能感兴趣的:(9.《汇编语言》-王爽第三版学习笔记 转移指令的原理)