转移指令的原理

转移指令有如下:

1.无条件转移指令(如:jmp)

2.条件转移指令

3.循环指令(如:loop)

4.过程

5.中断

操作符offset(取得标号的偏移地址)

jmp指令 --> 可以只修改IP ,也可以同时修改 CS 和 IP(实际是根据位移来转移的指令)

怎么计算位移

位移:该 jmp 要跳转到的标号内的第一个指令的偏移地址 减去(-)jmp 指令下一指令的偏移地址

机器码的字节数一般为 2 ~ 3 个字节 --> 机器本身的字节(1个字节) + 值的字节(寄存器的字节为2,al,ah等的字节为1)(值分为1字节值,如:21h --> (转化成汇编里的值)21 等,2字节值,如:2000h --> (转化成汇编里的值)0020),用来计算当前指令下一指令的偏移地址

jmp后的偏移地址为(即IP的值): jmp 下一条指令的偏移地址 + 位移(可能为正也可能为负)

https://fishc.com.cn/thread-27458-1-1.html
(借鉴的网站)

这里注意,此位移的计算只能适用于原有的语句,经过复制后得到的语句位移不变,即复制过后的语句的执行后的 ip == 该语句之下的一条语句 + 原有语句计算出来的位移

如:

首先我们能计算出 jmp short s 的 位移量 为 0008-0018 = -10(注意这里是十六进制的-10 --> (二进制)-16)
则执行 jmp short s 后ip 应该 == 0018 + (-10) == 0008 --> 恰好对应 s 的偏移地址
其次我们也能计算处 jmp short s1 的 位移量 为 0018-0022 = -10(注意这里是十六进制的-10 --> (二进制)-16)
由于 s 中的 jmp short s1 是复制过去的所以位移量不变 == 0018-0022 = -10 所以当执行 s 中的 jmp short s1 时
ip == 000A + (-10) = 0
可能的问题:
(1)s 中不是有两个 nop(nop指,这是一条空语句) 吗?为什么复制过后一个都没了呢? --> 这个跟机器码所占的字节有关,nop 所占的字节为 1,两个恰好是2字节,而jmp short s1 这条指令所占的字节为2字节,刚好覆盖了两个nop
(2)为什么使用000A来计算而不是0009来计算呢?--> 与问题1有关,复制后的代码应该如图:

可以清楚的看到0008和0009这两偏移地址被用来存放jmp short s1 这一语句了

需要:

转移的目的地址

转移的距离(段间转移,段内短转移,段内近转移)

jmp short 标号(转到标号处执行指令)

此种格式的jmp指令实现的是段内短转移
对IP的修改范围为 -128 ~ 127
即向前转移最多可以越过128个字节
向后转移最多可以越过127个字节

jmp near ptr 标号

该实现的是段内近转移
对IP的修改范围为 -32769 ~ 32767
即向前转移最多可以越过32769个字节
向后转移最多可以越过32767个字节

以上两种转移都是基于当前的IP的转移

jmp far ptr 标号

实现的是段间转移 --> 远转移

far ptr 指明了指令用标号的段地址和偏移地址,修改CS和IP

jmp 16为寄存器

功能:IP = (16位寄存器所存的值)
(1)jmp word ptr 内存单元地址(段内转移)
该内存单元地址处开始存放着一个字(数据),该字(数据)就是转移的目的偏移地址
(2)jmp dword ptr 内存单元地址(段间转移)
该内存单元地址处开始存放着一个两个字(数据),高地址处的字(数据)是转移的目的的段地址,低地址处的字(数据)是转移的目的的偏移地址(第一个字(数据)为低地址,第二个字(数据)为高地址)

所有的有条件转移指令都是段转移,对IP的修改范围都为 -128 ~ 127

jcxz指令(有条件转移指令)

格式:jcxz 标号

如果 cx = 0 那么转移到标号处执行
反之,则执行该语句的下一条指令,即跳过jcxz指令

loop指令(有条件转移指令)

格式 loop 标号

如果 cx != 0 那么转移到标号处执行
反之,则执行该语句的下一条指令,即跳过jcxz指令

值得注意的是,loop的指令执行时,首先dec cx,后才判断cx是否为0 --> 是否继续循环 (可以利用这个判断机制完成9.3的检测(不需要jcxz指令))

posted @ 2023-04-15 11:23  TFOREVERY  阅读(120)  评论(0编辑  收藏  举报