转移指令的原理

可以修改IP,或者同时修改cs和ip的指令统称为转移指令。
8086cpu的转移行为有以下几类:

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

根据转移指令对于ip的修改范围不同,所以段内转移又分为:短转移和近转移

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

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

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

不同转移指令的转移条件可能不同,但是转移的基本原理是相同的

操作符offset

offset是在汇编语言中是由编译器处理的符号,功能为取得标号的偏移地址。也就是相对于代码段的偏移地址,就是直接IP值了。

jmp指令

jmp为无条件转移指令,可以只修改IP,也可以同时修改cs和ip。
jmp指令需要给出两种信息:

  • 转移的目的地址
  • 转移的距离(段间转移,段内短转移,段内近转移)

不同的给出目的地址的方法不同,和不同的转移位置,对应有不同格式的jmp指令。

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

  1. jmp short 标号 (IP)=(IP)+8位位移
    这种格式的jmp指令实现的是段内短转移。对ip的修改范围限定为-128~127之间,可以看出正好是一个字节能够表示的范围。
  2. jmp near ptr 标号 (IP)=(IP)+16位位移
    jmp short功能相同,只不过他实现的是段内近转移。简单来说就是转移的距离拉长(虽然仍然是在段内)

小贴士
可以看到jmp shortjmp near ptr(段内转移)并没有直接将转移的目的地址直接写入机器指令中。而是将一个相对偏移地址写入了机器指令。(但是debug在对应的汇编指令中会看到偏移地址)
具体来说就是将标号地址相对于jmp指令的下一条指令的地址写入了机器指令。
也就是说,cpu在执行jmp指令的时候并不需要转移的目标地址。
UTOOLS1561367196752.png

转移的目的地址在指令中的jmp指令

前面讲到的段内转移指令其机器指令中并没有转移的目的地址,而是相对于当前ip的转移位移。
jmp far ptr 标号实现段间转移,又称为远转移。
(CS)=标号所在段的段地址;(IP)=标号在段中的偏移地址
far ptr将标号的地址写入了汇编指令。
UTOOLS1561367856893.png

jmp指令的机器码为EA,可以很明显的看出来,其中高地址放段地址,低地址放偏移地址。
顺便说明,像是jmp 1000:0是在debug中使用的,在汇编代码中并不能使用这样的指令。

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

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

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

转移地址在内存中的jmp指令有两种格式:

  1. jmp word ptr 内存单元地址(段内转移)
    更改ip值。
  2. jmp dword ptr 内存单元地址(段间转移)
    目标内存中放着两个字,其中高地址处的字为转移目标的段地址,低地址处的字为转移的目标的段偏移地址。
    (CS)=(内存单元地址+2)
    (IP)=(内存单元地址)

jcxz指令

jcxz为条件转移指令。所有的条件转移指令都是短转移指令,在对应的机器码中包含转移的位移,而不是目的地址。对IP的修改范围为-128~127.
功能:当cx寄存器的值为0是执行转移,否则什么也不做。

loop指令

loop指令为循环指令,所有的循环指令都是短转移。

根据位移进行转移的意义

高端大气的说法就是方便了程序段在内存中的浮动装配
实际上就是无所谓程序在内存中的地址,程序中的转移指令无需改变。

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

根据位移进行转移的指令,他们的转移范围收到转移位移的限制,如果在源程序中出现了转移范围超界的问题,在编译的时候,编译器将会报错。

分析一个奇怪的程序

就是一个计算通过相对偏移位置计算偏移位置的问题。
UTOOLS1561372732806.png

会注意到在执行完mov cs:[di], ax以后,s段的9090(nop nop)变成了EBF6(值为F6EB【小端序】)。同时想到的是同样都是EBF6却翻译出了不同的汇编指令。然而实际上都是相同的,翻译的问题是编译器做的。他将机器码翻译了以下,也就是将相对偏移地址直接翻译成为了IP中的偏移地址。
即使上面讲到过的偏移地址=jmp的下一条指令地址+相对偏移地址(注意到F6的问题,计算机中的数据以补码方式存储)。他就是将偏移地址算了出来。

根据材料编程

答案:

assume cs:code, ds:data
data segment
 db 'welcome to masm!' ; 文字
 db 00000010B, 00100100B, 01110001B ; 属性
data ends

code segment
start:
 mov ax, data
 mov ds, ax

 mov ax, 0b800H 
 mov es, ax 

 mov bx, 0
 mov si, 0
 mov di, 64
 mov bp, 6e0H 

 mov cx, 3
ln: 
 mov dx, cx
 mov cx, 16

 mov bx, 0
 mov di, 64
s:
 mov al, [bx]
 mov ah, 16[si]
 mov es:[bp].[di], ax

 inc bx
 add di, 2
 loop s

 add si, 1
 add bp, 160
 mov cx, dx
 loop ln

 mov ax, 4c00H
 int 21H

code ends
end start

注意数值不能以字母开头





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值