硬编码X86

硬编码:机器指令

硬编码结构

 说明:一共有六部分,第一部分前缀指令,只管自己,Opcode是这六部分的核心,Opcod决定ModR/M,ModR/M决定SIB,这三部分是这整条指令的核心,后面两部分属于“配角”,(偏移量和立即数)由核心决定

一.前缀指令(“:”)

分组:

定义说明指令
LOCK和REPEAT前缀指令LOCK(锁地址总线,多核情况下某时刻只允许一个核读这条指令)F0
 REPNT/REPNZ(重复执行后面的指令)F2
 REP/REPZ(重复执行后面的指令)F3
段前缀指令改变默认,明确告诉使用哪个段寄存器(双向 16位->32位 32位->16位)CS(2E) SS(36) DS(3E) ES(26) FS(64) GS(65)
地址宽度前缀指令改变默认,明确告诉使用那种寻址方式(双向 16位->32位 32位->16位)67
操作数宽度改变默认,改变操作数的宽度双向 16位->32位 32位->16位66

使用; 最多四个,一组一个,四个字节,最少0个,没有顺序
 

二.定长指令和变长指令

关键表格
Zz表示法 技巧:E和G–>变长

1. 定长指令

Opecode确定后指令长度确定,Opcode 后没有ModR/M,上图中圈出来的是比较常用的定长指令

(1)经典的定长指令_修改ERX

  • PUSH/POP                                             50系列
  • INC/DEC                                                40系列
  • Mov Rb,Ib                                              0xb0-0xb7系列
  • Mov ERX,Id                                            0xb8-0xbF系列
  • XCHG (交换两个寄存器的值)                0x90-0x97系列
前八列:
50 <–> push eax
51 <–> push ecx
52 <–> push edx
53 <–> push ebx
54 <–> push esp
55 <–> push ebp
56 <–> push esi
57 <–> push edi
后八列:
58 <–> pop eax
59 <–> pop ecx
5A <–> pop edx
5B <–> pop ebx
5C <–> pop esp
5D <–> pop ebp
5E <–> pop esi
5F <–> pop edi

寄存器编号

这里写图片描述

(2)经典的定长指令_修改EIP


0x70-0x7F

条件跳转:Opcode后面跟一个立即数的偏移,因此指令共两个字节
立即数是有符号的:最高位为0(7F)向下跳,最高位为1(80)向上跳

<1>条件跳转,后跟一个字节立即数的偏移(有符号),共两个字节
<2>如果条件成立,跳转到 当前指令+当前指令长度+Ib
<3> 最大值,向前跳7f,向后跳80

硬编码汇编指令
0x70JO
0x71JN0
0x72JB/JNAE/JC
0x73JNB/JAE/JNC
0x74JN/JE
0x75JNZ/JNE
0x76JBE/JNA
0x77JNBE/JA
0x78JS
0x79JNS
0x7AJP/JPE
0x7BJNP/JPO
0x7CJL/JNGE
0x7DJNL/JGE
0x7EJLE/JNG
0x7FJNLE/JG

 

0x0F 0X80 -0X0F 0X8F

0F80~0F8F远距离JCC跳转:
后面跟一个四字节的立即数,指令长共6字节。立即数正负以7FFFFFFF、80000000为界。0F800F8F和707F对应列的指令一样只不过立即数字节数不同。

<1>条件跳转,后跟四个字节立即数的偏移(有符号),共五个字节
<2>如果条件成立,跳转到 当前指令+当前指令长度+Id
<3> 最大值,向前跳7FFFFFFFF,向后跳80000000

硬编码汇编指令
0x0F 0X80JO
0x0F 0X81 JN0
0x0F 0X82JB/JNAE/JC
0x0F 0X83JNB/JAE/JNC
0x0F 0X84JN/JE
0x0F 0X85JNZ/JNE
0x0F 0X86 JBE/JNA
0x0F 0X87JNBE/JA
0x0F 0X88 JS
0x0F 0X89JNS
0x0F 0X8A JP/JPE
0x0F 0X8BJNP/JPO
0x0F 0X8C JL/JNGE
0x0F 0X8DJNL/JGE
0x0F 0X8EJLE/JNG
0x0F 0X8F JNLE/JG


  其他指令

定义说明字节数
0xE0LOOPNE/LOOPNZ Ib(jb) ECX=ECX-1 当ZF=0&&ECX!=0时跳转到当前指令地址+当前指令长度+Ib 2
0xE1LOOPE/LOOPZ Ib(jb) ECX=ECX-1 当ZF=1&&ECX!=0时跳转到当前指令地址+当前指令长度+Ib2
0xE2LOOP Ib(jb) ECX=ECX-1 当ECX!=0时跳转到当前指令地址+当前指令长度+Ib2
0xE3JrCXZ Ib(jb) (在32位模式中,rCX为ECX) 当ECX=0时跳转到当前指令地址+当前指令长度+Ib(自己控制步长)2
0xE8 CALL Id(jd) ECX=ECX-1 CALL指令的下一跳指令地址入栈后,跳转到当前指令地址+当前指令长度+Id  5
0xE9 JMP Id(jd) 跳转到当前指令地址+当前指令长度+Id    5
E0 <–> loopne/loopnz Ib(dec ecx) (ZF=0 && ECX != 0)
E1 <–> loope/loopz Ib(dec ecx) (ZF=1 && ECX != 0)
E2 <–> loop Ib(dec ecx) (满足ECX != 0就跳转)
E3 <–> jecxz/jrcxz Ib (满足ECX=0跳转)
注意: Ib即为byte类型立即数(Immediate data),Iw则是Immediate data word,Id即为Immediate data dword,Ap即六字节长度的直接地址

E8 <–> call Id
E9 <–> jmp Id
EA <–> jmp Ap,jmp CS:Id (**前四个字节为跳转地址,后两个字节为段选择子.**即高两字节赋给CS,低四字节赋给EIP)
EB <–> jmp Ib
FF <–> call dword ptr [edx]
E8call为直接call,call后面的地址即为要跳转的地址,FFcall为间接call,后面跟的内存那只能够存放着即将要跳转的地址。比如用对象指针访问一个普通成员函数和一个虚函数,其call的硬编码都不同


其他指令

定义说明字节数
0xEAJMP Ap(Ap:六字节长度的而直接地址)JMP CS:Id 将AP中的高两位赋值给CS,低4位直接赋值给EIP,即跳转 7
0xEB JMP Ib(Jb)跳转到当前指令地址+当前指令长度+Ib     
0xC3 RET EIP出栈 1
0xC2RETF lw EIP出栈后,ESP=ESP+iw3
0xCBRETF(return far) 出栈8个字节,低于4个字节赋值给EIP,高4个字节中低2位赋值给CS1
0xCA RETF lw 出栈8个字节,低于4个字节赋值给EIP,高4个字节中低2位赋值给CS后,ESP=ESP+Iw 3

        

2.变长指令

Opecode确定后指令长度不确定,Opcode 后紧跟ModR/M

经典的变长指令

   

(1)ModRM

当指令中出现内存操作对象的时候,就需要在操作码后面附加一个字节来进行补充说明,这个字节被称为ModR/M,该字节的8个位被分为三部分

ModR/M的结构

其中,Reg/Opcode(第3、4、5位,共3个位)描述指令中的G部分,即寄存器查看下表

寄存器G部分对应表

Mod(第6、7位)和R/M(第0、1、2位)共同描述指令中的E部分,即寄存器/内存查看下表

该表不全 

(2)RegOpcode (一个字节8位)
Reg/Opcode(第3、4、5位,共3个位)除描述寄存器外还可描述Opcode,也就是描述执行什么命令
80 81 82 83这四个指令

(3)SIB(一个字节8位)
R/M为100,后面会跟着SIB,SIB的作用是解决Mod和R/M无法把偏移量和立即数的格式描述清楚时,类似下图不确定的格式,
100

 SIB的格式

SIB的格式

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值