(九)汇编语言——转移指令的原理
文章目录
- (九)汇编语言——转移指令的原理
- 转移指令
- 作用
- 分类
- 转移行为
- 转移距离
- 转移指令
- 操作符offset
- jmp指令
- 功能
- 原理
- 段间转移
- 段内转移
- 短转移
- 原理
- 长转移
- 原理
- 位移越界
- 转移地址
- 寄存器
- 内存
- 段内转移
- 段间转移
- jcxz指令
- 功能
- loop指令
- 功能
- loop指令
- 功能
- 总结
接下来我们要介绍的是有关汇编语言里面的转移指令,其实对于转移指令我们已经接触过了,那就是之前用来改变CS地址的 jmp 指令,还有循环指令 loop ,其实都属于转移指令,但是之前我们并没有详细介绍原理,所以我们接下来就详细介绍一下他们的原理,并且介绍一些其他的转移指令,帮助我们的程序更加的优美与饱满,好啦,就让我们开始进入今天的学习内容吧!
转移指令
一般情况下指令是顺序地逐条执行的,而在实际中,经常需要改变程序的执行流程,所以这个时候,转移指令就显得十分重要了。
作用
转移指令,可以控制CPU执行内存中某处代码的指令;也可以修改IP,或同时修改CS和IP的指令。
分类
转移指令可以按照转移行为、转移距离和转移指令去分类,我们就来看看是如何进行分类的吧!
转移行为
按照转移行为去分类,大致可以分为:
- 段内转移:只修改IP,如 jmp ax
- 段间转移:同时修改CS和IP,如 jmp 1000:0
转移距离
按照转移距离去分类,大概可以分为:
- 段内短转移:IP修改范围为 -128 ~ 127
- 段内近转移:IP修改范围为 -32768 ~ 32767
转移指令
按照转移指令去分类,大概可以分为:
- 无条件转移指令(如:jmp)
- 条件转移指令(如:jcxz)
- 循环指令(如:loop)
- 过程
- 中断
操作符offset
这个操作符offset,主要的功能就是取得标号的偏移地址,我们举个例子。
assume cs:codeseg
codeseg segment
start: mov ax,offset start ;相当于 mov ax,0
s: mov ax,offset s ;相当于 mov ax,3
codeseg ends
end start
jmp指令
jmp指令的话,我们之前简单介绍过,接下来,我们来详细的介绍一下这个指令。
功能
无条件转移,可以只修改IP,也可以同时修改CS和IP。但是呢,我们使用jmp指令的话,需要给出两种信息:第一就是转移的目的地址,其次就是转移的距离,具体分为以下三种:
- 段间转移(远转移):jmp 2000:1000
- 段内短转移:jmp short 标号;IP的修改范围为-128~127,8位的位移
- 段内近转移:jmp near ptr 标号;IP的修改范围为-32768~32767,16位的位移
原理
为了我们讲解关于jmp指令的原理,我们举一个例子来讲解,这样应该比较好理解一点。
assume cs:codesg
codesg segment
start:mov ax,0
jmp short s
add ax,1
s:inc ax
mov ax,4c00h
int 21h
codesg ends
end start
我们将这段代码放到debug里面去看一下,具体的机器指令。
我们可以看到,jmp的后面跟着的确实是0008,也就是s处的地址,但是机器指令却是EB03,我们主要就是研究一下这个机器指令。
EB03,主要就是03,它代表着什么含义呢?其实这个03的含义是:下一条指令加上03,我们看下一条指令的地址刚好是0005,加上03,刚好就是0008,也就是下一条指令的地址。所以我们说,这个机器码,其实不是地址,而是位移。
我们再来仔细看一下这段代码的执行过程:
- (IP)=0003,CS:IP指向EB03(jmp的机器码)
- 读取指令码EB03进入指令缓冲器;
- (IP)=(IP)+所读取指令的长度=(IP)+2=0005,CS:IP指向add ax,0001;
- CPU执行指令缓冲器中的指令EB03;
- 指令EB05执行后,(IP)=(IP)+03=0008H,CS:IP指向inc ax
段间转移
远转移:jmp far ptr 标号,实现的是段间转移。far ptr指明了跳转到的目的地址,即包含了标号的段地址CS和偏移地址IP。也就是说,远转移指令的机器码是包含了CS和IP的。
段内转移
段内转移主要分为两种,一个是短转移,一个就是近转移,接下来我们来介绍一下。
短转移
短转移:“jmp short标号”;功能:(IP)=(IP)+8位位移
原理
- 8位位移=“标号”处的地址 - jmp指令后的第一个字节的地址(也就是位移);
- short指明此处的位移为8位位移;
- 8位位移的范围为-128~127,用补码表示;
- 8位位移由编译程序在编译时算出。
长转移
近转移:指令“jmp near ptr 标号”;功能:(IP)=(IP)+16位位移
原理
- 16位位移=“标号”处的地址 - jmp指令后的第一个字节的地址也就是位移);
- near ptr指明此处的位移为16位位移,进行的是段内近转移;
- 16位位移的范围为-32769~32767,用补码表示;
- 16位位移由编译程序在编译时算出。
位移越界
这个其实很好理解,比如8位的位移,但是位移距离却是16位的,就会出现这种情况,这种情况是会报错的,程序也无法运行,所以我们选用指令的 时候需要注意。
转移地址
上面的都是转移地址为标号的情况,接下来我们来介绍一下其他的几种情况。
寄存器
指令格式:jmp 16位寄存器,这个和标号是类似的,就不再详细介绍了。
内存
也是分为段内转移和段间转移,我们来一一介绍。
段内转移
jmp word ptr 内存单元地址,就是从内存单元地址处开始存放着一个字,是转移的目的偏移地址。
段间转移
jmp dword ptr 内存单元地址,就是从内存单元地址处开始存放着两个字,高地址处的字是转移的目的段地址,低地址处是转移的目的偏移地址。
jcxz指令
指令格式:jcxz标号,简而言之,就是如果cx寄存器为0,就跳转。所以我们说jcxz是有条件转移指令。
功能
如果(cx)=0,则转移到标号处执行,当(cx)≠0时,什么也不做(程序向下执行)
当(cx)=0时,(IP)=(IP)+8位位移)
- 8位位移=“标号”处的地址 - jcxz指令后的第一个字节的地址;
- 8位位移的范围为-128~127,用补码表示;
- 8位位移由编译程序在编译时算出。
loop指令
这个之前介绍过了,就简单介绍一下。指令格式:loop 标号
功能
如果(cx)≠0,(IP)=(IP)+8位位移
- 8位位移=“标号”处的地址-loop指令后的第一个字节的地址
- 8位位移的范围为-128~127,用补码表示
- 8位位移由编译程序在编译时算出
算出。
loop指令
这个之前介绍过了,就简单介绍一下。指令格式:loop 标号
功能
如果(cx)≠0,(IP)=(IP)+8位位移
- 8位位移=“标号”处的地址-loop指令后的第一个字节的地址
- 8位位移的范围为-128~127,用补码表示
- 8位位移由编译程序在编译时算出
总结
加油,冲冲冲!!!!!!!!!