汇编09:转移指令的原理

转移指令的原理

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

转移行为有很多种不同的分类方法:

根据只修改IP和同时修改CS和IP,可以分为段内转移(jmp ax)和段间转移(jmp 1000:0)

根据指令对IP的修改范围不同,段内转移又分为短转移(IP的修改范围为-128-127)和近转移(IP的修改范围-32768-32767)

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

1、无条件转移指令,如jmp

2、条件转移指令

3、循环指令,如loop

4、过程

5、中断

操作符offset

offset是一个伪指令,它的功能是取得标号的偏移地址,如:

assume cs:codesg
codesg segment
	start:	mov ax,offset start
	s:	mov ax,offset s
codesg ends
end start

第三行语句中的offset start就相当于0,因为start标号的偏移地址为0;第四句中的offset s就相当于3,因为s标号的偏移地址为3,这是由于第一条指令长度为3个字节。

有了offset我们就可以方便的取到标号的偏移地址了,我们可以先设置一个标号中放入nop(占1个字节的机器码):

s0:	nop
	nop

然后再将其他标号s处的指令直接复制过去:

mov si,offset s
mov di,offset s0
mov ax,cs:[si]
mov cs:[di],ax

jmp指令

jmp为无条件转移指令,它要给出两种信息:要转移的目的地址,或者要转移的距离。

转到标号处执行指令

使用格式:

jmp short 标号

它实现的是段内短转移,对IP的修改范围为-128-127,也就是说它向前转移时最多可以越过128个字节,向后转移时可以最多越过127个字节,转移指令结束后,CS:IP应该指向标号处的指令。

值得注意的是,这个指令对应的机器码中是没有转移的目的地址的,而是包含转移的位移,编译器根据两点的距离计算出位移量,然后修改IP寄存器中的值,在编译结束后的机器指令中就包含转移位移了。相当于该指令的作用其实是(IP)=(IP)+8位位移。

对应的段内近转移指令:

jmp near ptr 标号

他对IP的修改范围为-32768-32767.相当于(IP)=(IP)+16位位移。

对应的远转移指令(段间转移):

jmp far ptr 标号

这个指令对应的机器码中就包含了转移的目的地址了。

使用内存地址和寄存器

jmp可以直接加16位reg:

jmp 16位reg

它的意思就是修改IP寄存器的值,修改为对应寄存器中的值。

jmp命令中也可以直接包含地址,它有两种形式:

1、只修改IP的段内转移:

jmp word ptr ds:[0]

相当于把对应地址的值赋值给IP寄存器,完成转移。

2、同时修改IP和CS的段间转移:

jmp dword ptr ds:[0]

从对应内存地址单元中取出两个字,低地址的那个字赋值给IP,高地址的那个字赋值给CS,完成转移。

jcxz指令

jcxz为有条件转移指令,所有的有条件转移指令都是短转移,在对应的机器码中包含转移的位移,而不是目的地址。对IP的修改都是-128-127.

使用格式:

jcxz 标号

相当于如果cx寄存器中的值是0,就执行:

jmp short 标号

loop指令

loop指令是循环指令,所有的循环指令都是短转移,基本使用用法:

loop 标号

相当于:

(cx)--
if((cx)!=0)jmp short 标号

关于转移位移的讨论

在上述段内转移指令中,我们可以发现这些指令对应的机器码中只有转移的相对位移,而不包含转移的目的地址,这种设计是为了方便程序段在内存中的浮动装配。

如果我们自定义的程序要直接引用某个写好的目标文件,这个文件内部的转移写成段内转移,这样就可以保证在连接时不会出错,不会因为该目的地址有其他内容而覆盖。

此外还要注意位移超界的问题,如果转移范围出现超界,编译器会报错。

posted @ 2020-04-30 22:28  勇闯8  阅读(327)  评论(0编辑  收藏  举报