E8 cw
cw 表示E8后面跟随2 字节 (什么数不知道)
rel16 指在与指令同一代码段内的相对地址偏移
D ,指向Instruction Operand Encoding 表中的D列, 他告诉我们 操作数1 是一个0FFSET
N.S. 在64位模式下,某些指令需要使用“地址覆盖前缀”(address override prefix),但这并不被所有处理器支持。如果在64位模式下使用地址覆盖前缀,可能会导致特定处理器型号的执行行为出现不一致或错误。
Valid 表示兼容模式和传统模式下,这个指令是有效的
Description: 调用指令”(Call)是一种“近跳”(near jump)指令,它的目标地址是相对于下一条指令的偏移量(displacement)
可以看到在32位的情况下,默认的操作数大小为 32位, 所以我门需要添加 66前缀,改变操作数的大小
E8 cd
cd 表示后跟4字节
rel32 :指在与指令同一代码段内的相对(relative )地址偏移
Description:它的目标地址是相对于下一条指令的偏移量(displacement)
在相对寻址中,可以上下寻址, 相对偏移可以是正数,往下跳,如果是负数,往上跳
下面的例子中,FFFF FFFA 表示十进制的 -6 ,也就是相对 77261B78 偏移-6 的地址就是77261B72
9A cp
cp:在操作码后跟随的值的字节大小为6字节
ptr16:32:冒号左边的值是一个16位选择子或用于代码段寄存器的值。右侧的值对应目标段内的偏移量。
Description: 远跳转 ,绝对( absolute,),地址在操作数中给出
请留意这个汇编代码的编写格式 call far 0x0023:0x77261B72
在32位 保护模式中,段的base都是从0开始,所以目标段内的偏移量是0x77261B72
在opcode 的后6个字节中,72 1B 26 77 23 00 ,是按照小端序排列的
不知道你注意到没有, 在执行这个远跳转时, 除了返回的rip ,还有一个参数被压入栈中 ---23
如果我执行 77261B72 这个地址的ret指令,你猜会发生什么事情.
堆栈将无法平衡!!!!!!!!!!!!!!!!!!!!!!!!!!
并且,23 到底是什么东西
请翻阅 英特尔手册 第一卷的 6.4.2 Far CALL 和 RET 操作 将会找到答案
FF /2
/2 | 表示mod/rm字段 中 reg字段==2 |
r/m32 | 表示一个32位通用寄存器或内存操作数,用于指令的操作数大小属性为32位的情况。32位通用寄存器包括 EAX、ECX、EDX、EBX、ESP、EBP、ESI、EDI。在64位模式下,通过使用 REX.R 前缀,还可以访问 R8D 到 R15D 这些32位寄存器。 |
M | 表示 在 Instruction Operand Encoding 表 的M列中, Operand 1 在 ModRM字段的:r/m 字段中,并且将被读取(r) |
Description: | 近跳转,绝对 ,间接, 地址在r/m32中给出 |
翻阅 写文章-CSDN创作中心关于opcode从零开始的补充2-CSDN博客 写文章-CSDN创作中心 中 2.1.3 ModR/M and SIB Bytes章节
中的表 Table 2-2. 32-Bit Addressing Forms with the ModR/M Byte
我通过表,构造了如下的 指令 ,注意我没有通过汇编代码生成,都是使用 二进制代码编写
所以请你注意汇编指令的书写方式
请你注意 绝对的 和 间接的绝对的 跳转 的跳转两种方式的不同
FF/3
/3 | 表示mod/rm字段 中 reg字段==3 |
m16:32 | 表示包含一个由两个数字组成的远指针的 内存操作数。冒号左边的数字表示段选择符,右边的数字表示段内偏移量。 |
M | 和上面的意义相同 |
Description | 在64位模式下,RIP(指令指针寄存器)的更新规则如下 如果选择子(selector)指向一个门(gate):此时,RIP 的值将被设置为从该门中获取的64位位移(displacement)。 如果选择子没有指向门,则 RIP 将被设置为从指令中引用的远指针(far pointer)中获取的32位偏移(offset),并进行零扩展(zero extended)到64位。 |
在构建 m16:32 时, 你需要在内存地址中构建一个 6字节的数,
这个数和使用绝对寻址的形式需要一样
并将地址放入eax寄存器中
下面的代码帮助你记忆char buff[6]; *(DWORD*)&buff[0] = 0x77261b72; //段内偏移 *(WORD*)&buff[4] = 0x23; //段选择子 __asm { call fword ptr[buff]; }
可以看到,我们没有 跨特权级,在调用call之后 堆栈中
esp==>返回地址
esp==>原来的cs段选择子
下一篇描述 jump指令
如有问题,请联系qq1490900437