第九章 转移指令的原理
9.0 转移的分类:
1)转移行为的分类:
段内转移,段外转移(短转移,近转移)
2)转移指令的分类:
* 无条件转移指令
* 条件转移指令
* 循环指令
* 过程
* 中断
9.1 操作符 offset
操作符offset在汇编语言中作用是 获取标号的偏移地址 。
这里是偏移地址,并没有其段地址。
如果要段地址,则相应的加上其段地址寄存器。
mov si, offset s
表示的是将’s’段中的地址存入到寄存器’si’中。
之后可以使用 cs:[si]
来表示这个地址。
9.2 jmp指令
jmp为无条件转移指令,可以只修改IP,也可以同时修改CS和IP。
jmp指令主要给出两种信息:
- 转移的目的地址
- (段间转移,段内短转移,段内近转移)
9.3 依据位移进行转移的jmp指令
jmp short 标号(转到标号处执行指令)
这种格式的指令是实现段内段转移,修改范围是-128~127。
jmp指令中的“short”符号,说明进行短转移。
标号指明了指令要转移的目的地址,转移指令结束后,CS:IP应该指向标号处的指令。
CPU执行指令的过程:
- 从CS:IP指向内存单元读取指令,读取的指令进入指令缓冲器。
- (IP)=(IP)+所读取的指令长度,从而指向下一条指令。
- 执行指令。转到1,重复这个过程。
jmp short 标号
的执行原理:(IP)=(IP)+8位地址。
- 8位位移=标号处的地址-jmp指令后的第一个字节的地址。(因为读取完之后IP会立刻跳转到后面)
- short指明此处的位移为8位。
- 8位位移的范围为-128~127,用补吗表示。
- 8位位移由编译程序在编译时算出。
near
则表示的是十六位。
9.4 转移的目的指令在指令中的jmp指令
前面讲的jmp指令,其对应的机器指令中并没有转移的目的地址,而是相对于当前IP进行转移位移的。
jmp far ptr 标号
实现的是段间转移,又称为远转移。
CS=标号所在段的段地址;IP=标号在段中的偏移地址。
far ptr 指明了指令用标号的段地址和偏移地址修改CS和IP/
jmp far ptr s
跳转到s段开头。其被编译的机器语言是EA0B01BD0B
其中低字节 0B01 是偏移地址,高字节 BD0B 是段地址。
9.5 转移地址在寄存器中的jmp指令
jmp 16位 reg
,功能是(IP)=(16位reg),寄存器来修改IP地址。
9.6 转移地址在内存中的jmp指令。
注意这是获取内存中存储数字的地址,而非CS:IP指向该内存。
转移指令有下面两种格式:
- 段内转移:
jmp word ptr ds:[0]
一个word位两个字节,共16位,来表示出ds:[0]
中存储的数字,其作为偏移地址来表示出来。
mov ax,0123H
mov [bx],ax
jmp word ptr [bx]
必须要声明是
word
,因为这就会接下来读取两位而不是一位,这种概念要理解。
- 段间转移:
jmp dword ptr ds:[0]
两个word位一共四个字节,前两个低位存取偏移地址,后两个高位存取段地址。
mov ax,0123H
mov [bx],ax
mov word ptr [bx+2],0
jmp dword ptr [bx]
执行后 CS=0000,IP=123H。
9.7 jcxz指令
jcxz指令是有条件的转移指令,从它字面上的意思来讲是jmp if cx == zero
利用jcxz指令,实现查找内存中的第一个值为0的字节
start: mov ax,2000H
mov ds,ax
mov bx,0
s: mov ch,0
mov cl,[bx]
jcxp ok
inc bx
jmp short s
ok: mov dx,bx
mov ax,4c00h
int 21h
注意:字节往寄存器中存储,如果你不分高低位,那么会一次读入两个字节,从而无法明确区分,我们要处理的是位,这个概念是要明确的。
9.8 loop指令
loop指令为循环指令,所有的循环指令都是短指令,在对应的机器码中包含转移的位移,而不是目的地址。对IP的修改范围为:-128~127。
操作方法如下:
1. cx=cx+1
2. 如果cx!=0,IP=IP+8位位移。
用loop指令来查找内存中为第一个值为0的字节
关键代码
mov cl,[bx]
mov cx,0
inc cx
inc bx
loop s
因为loop在进行前先来让cx-1,所以必须先给cx加一,这种操作是明确的。
9.9 根据位移进行转移的意义
我们为什么要进行位移转移,而不直接给出程序的目的地址呢?
因为这 方便了程序段在内存中的浮动装置。
考虑不同的环境中程序的内存所处的地址是一直在变化的,所以给出目的地址,让计算机再去计算实际的,其实很麻烦的,但如果知道相对位移,无论在哪儿在一个程序中的相对位移都是不会变化的,这样就很简单了。
9.10 编译器对转移位移超界的检测
如果在源程序中出现了转移位移范围超界问题,在编译的时候,编译器将报错。