硬编码_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 |
- 使用; 最多四个,一组一个,四个字节,最少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
(2)经典的定长指令_修改EIP
I
0x70-0x7F
<1>条件跳转,后跟一个字节立即数的偏移(有符号),共两个字节
<2>如果条件成立,跳转到 当前指令+当前指令长度+Ib
<3> 最大值,向前跳7f,向后跳80
硬编码 | 汇编指令 |
---|---|
0x70 | JO |
0x71 | JN0 |
0x72 | JB/JNAE/JC |
0x73 | JNB/JAE/JNC |
0x74 | JN/JE |
0x75 | JNZ/JNE |
0x76 | JBE/JNA |
0x77 | JNBE/JA |
0x78 | JS |
0x79 | JNS |
0x7A | JP/JPE |
0x7B | JNP/JPO |
0x7C | JL/JNGE |
0x7D | JNL/JGE |
0x7E | JLE/JNG |
0x7F | JNLE/JG |
II
0x0F 0X80 -0X0F 0X8F
<1>条件跳转,后跟四个字节立即数的偏移(有符号),共五个字节
<2>如果条件成立,跳转到 当前指令+当前指令长度+Id
<3> 最大值,向前跳7FFFFFFFF,向后跳80000000
硬编码 | 汇编指令 |
---|---|
0x0F 0X80 | JO |
0x0F 0X81 | JN0 |
0x0F 0X82 | JB/JNAE/JC |
0x0F 0X83 | JNB/JAE/JNC |
0x0F 0X84 | JN/JE |
0x0F 0X85 | JNZ/JNE |
0x0F 0X86 | JBE/JNA |
0x0F 0X87 | JNBE/JA |
0x0F 0X88 | JS |
0x0F 0X89 | JNS |
0x0F 0X8A | JP/JPE |
0x0F 0X8B | JNP/JPO |
0x0F 0X8C | JL/JNGE |
0x0F 0X8D | JNL/JGE |
0x0F 0X8E | JLE/JNG |
0x0F 0X8F | JNLE/JG |
III
其他指令
定义 | 说明 | 字节数 |
---|---|---|
0xE0 | LOOPNE/LOOPNZ Ib(jb) ECX=ECX-1 当ZF=0&&ECX!=0时跳转到当前指令地址+当前指令长度+Ib | 2 |
0xE1 | LOOPE/LOOPZ Ib(jb) ECX=ECX-1 当ZF=1&&ECX!=0时跳转到当前指令地址+当前指令长度+Ib | 2 |
0xE2 | LOOP Ib(jb) ECX=ECX-1 当ECX!=0时跳转到当前指令地址+当前指令长度+Ib | 2 |
0xE3 | JrCXZ 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 |
IV.
其他指令
定义 | 说明 | 字节数 |
---|---|---|
0xEA | JMP Ap(Ap:六字节长度的而直接地址)JMP CS:Id 将AP中的高两位赋值给CS,低4位直接赋值给EIP,即跳转 | 7 |
0xEB | JMP Ib(Jb)跳转到当前指令地址+当前指令长度+Ib | |
0xC3 | RET EIP出栈 | 1 |
0xC2 | RETF lw EIP出栈后,ESP=ESP+iw | 3 |
0xCB | RETF(return far) 出栈8个字节,低于4个字节赋值给EIP,高4个字节中低2位赋值给CS | 1 |
0xCA | RETF lw 出栈8个字节,低于4个字节赋值给EIP,高4个字节中低2位赋值给CS后,ESP=ESP+Iw | 3 |
2.变长指令
Opecode确定后指令长度不确定,Opcode 后紧跟ModR/M
(1)ModRM
当指令中出现内存操作对象的时候,就需要在操作码后面附加一个字节来进行补充说明,这个字节被称为ModR/M,该字节的8个位被分为三部分
其中,Reg/Opcode(第3、4、5位,共3个位)描述指令中的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无法把偏移量和立即数的格式描述清楚时,类似下图不确定的格式,
SIB的格式
查2-3表得具体形式