转移指令的原理
转移指令有如下:
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指令