汇编语言第九章——转移指令的原理

定义

什么是转移指令?
我们对其的定义如下:

可以修改IP,或同时修改CS和IP的指令统称为转移指令

简单来说,就是可以控制CPU执行内存中某段代码的指令。
我们先总的对这类行为进行一下分类。
从行为角度,主要有一下两类:

  1. 段内转移:只改变IP
  2. 段间转移:同时改变IP和CS

在考虑修改的范围:

  1. 短转移的IP范围:-128~127
  2. 近转移的IP范围:-32768~32767

所以我们就可以对转移指令进行分类:

  1. 无条件转移指令(如:jmp)
  2. 条件转移指令
  3. 循环指令(loop)
  4. 过程
  5. 中断

操作符offset

这个也是一个只由编译器执行的指令。
格式很简单:

offset [flag]

这里的flag就是之前说的标号,比如start。
所以我们使用时,就可以如下使用:

start:mov ax,offset start

也就是说,在编译时,会把offset start换成0.

注意:offset只取得偏移地址。

jmp指令

如之前说述,jmp是一个无条件指令,既可以修改IP,也可以同时修改CS:IP。
要成功转移地址,jmp需要两个信息:

  1. 转移的目的地址
  2. 转移的距离(段间转移、段内短转移、段内近转移)

下面我们将会对不同的使用方法,进行详细讲解。

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

先说一下格式:

jmp short [flag]

这里的short,指的就是段内短转移。
也就是说,我们最大只能向前移动128个字节,向后最大移动127字节。
这里的flag就是我们之前说的标号,比如:start。
具体的使用例子如下:

assume cs:code

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

所以在执行到jmp short s时,我们就会跳至inc ax,而不会执行add ax,1

值得注意的一点是:CPU在执行jmp指令时,不需要转移的目的地址
那么CPU是根据什么来转移的呢?
其实就是位移,而这里位移的计算,则是由编译器通过标号进行计算的。

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

我们先给出格式:

jmp far ptr [flag]

看到far,你可能会有所反应,这里是远转移,或是说段间转移。
我们也举个例子吧:

assume cs:code

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

你也许会好奇,这里和前面说的有什么不同的吗?
如果仅仅是看汇编代码,当然是看不出来的,我们如果把这些代码加载入内存,然后用debug去查看代码段中存储的内容,你就会看出二者的不同。这里就不展示了。

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

这个格式比较简单:

jmp [reg]

这里就是将reg的数值赋值给IP,即可实现,我们之前也见过很多了。不再赘述。

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

对于这个地址有两种格式:

jmp word ptr [内存单元地址]
jmp dword ptr [内存单元地址]

第一个,是从给的单元地址开始,读取一个字,作为目的地址的偏移地址。
第二个,是从给的单元地址开始,读取两个字,高位字作为段地址,低位字作为偏移地址。

jcxz指令

这个指令是有条件转移指令。
所有的有条件转移指令都是短转移。
提供的也是位移。
格式如下:

jcxz [flag]

那么为什么说它是有条件的呢?
因为它是如下执行的:
if((cx)==0)jmp short [flag]
如果(cx)不是0,那么就会继续向下执行,不会跳转。

loop指令

loop顾名思义,是循环指令,所有的循环指令也都是短转移。
也是通过位移进行转移。
格式也很简单:

loop [flag]

之前应该说过loop,以cx的值作为循环变量,这里就不再赘述了。

根据位移转移的意义

我们在日常生活中,我们的父亲可能会这么对我们说:“儿子,去超市帮我买点盐。”
然后,我们就出门去超市了。
我相信,应该不会有父亲会这么说:“儿子,你出门走100米,右转再走200米,再左转……最后走50米,在那里帮我买些盐”
那么我们为什么需要给出位移的转移而不是都给目的地址呢?
其实,这种设计是为了方便程序段在内存中的浮动装配。
也就是说这个代码段,装在内存的任意位置均可执行。
因为他们的绝对位置也许会改变,但是相对位置是不会变的。

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

我们在开头就说了,有短转移和近转移,他们转移的大小是有限制的,那么如果转移越界了会怎么样呢?
很简单,编译器报错。(笑)

结束语

我们的第九章就结束了,这一章主要说了转移指令。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值