如何让网站自适应手机廊坊关键词优化报价
定长指令与变长指令
Opcode可以看做是这一组指令的灵魂,是最重要的一部分,最少一个字节,最多3个字节
一条指令的长度(占多少个字节),主要是由Opcode
,ModR/M
,SIB
这三个决定(Opceode决定了后面有没有ModR/M,而ModR/M又决定了后面有没有SIB)
什么是定长指令?什么是变长指令?
上图中,55就是一个定长指令,cpu只需要通过一个55就可以决定指令的长度,而下面的00就是一个变长指令,cpu并不能只通过一个00指令来确定指令的长度
想要学好硬编码最重要的就是要学会如何查表 (A.2.4.1 One-Byte Opcode Instructions)
Opcode表
其中A.2.4.1 One-Byte Opcode Instructions是一个字节的操作码,对应的表是A-2,两个字节和三个字节在下面的目录都有体现
定长指令50
这张表如何查呢?我们先看纵向的值,再看横向的值比如,纵向为5,横向为0的硬编码
可以看到对应的硬编码为push,那push什么呢?我们看0对应的位置,是rax,那么这条指令就是push rax
,我们在x64dbg中验证一下,顺便看下51,52,53又是什么,看是不是和我们查表的结果一致
可以看到确实是和我们查表的结果一致
变长指令00
我们再查下变长指令00
可以看到对应的是我们的add指令,但是指令格式我们就有点看不懂了,是一个Eb,Gb这种,不像50对应的编码那样清晰,像这种就要使用到我们的Zz表示法
第一个大写就对应这边的描述,小写的就对应下面小写字母的描述
A.2.1 寻址方法编码(Codes for Addressing Method)
编码 | 英文说明 | 中文翻译 |
---|---|---|
A | Direct address: the instruction has no ModR/M byte; the address of the operand is encoded in the instruction. No base register, index register, or scaling factor can be applied (e.g., far JMP (EA)). | 直接地址:指令无 ModR/M 字节,操作数地址直接编码在指令中。不可使用基址/索引寄存器或比例因子(如 JMP FAR )。 |
B | The VEX.vvvv field of the VEX prefix selects a general-purpose register. | VEX.vvvv 字段:VEX 前缀的 vvvv 域选择通用寄存器。 |
C | The reg field of the ModR/M byte selects a control register (e.g., MOV (0F20, 0F22)). | 控制寄存器:ModR/M 的 reg 域选择控制寄存器(如 MOV CR0 )。 |
D | The reg field of the ModR/M byte selects a debug register (e.g., MOV (0F21, 0F23)). | 调试寄存器:ModR/M 的 reg 域选择调试寄存器(如 MOV DR0 )。 |
E | A ModR/M byte follows the opcode and specifies the operand. The operand is either a general-purpose register or a memory address (with optional segment/base/index/scaling/displacement). | ModR/M 寻址:操作码后跟 ModR/M 字节,指定寄存器或内存地址(可含段/基址/索引/比例因子/位移)。 |
F | EFLAGS/RFLAGS Register. | EFLAGS/RFLAGS 寄存器。 |
G | The reg field of the ModR/M byte selects a general register (e.g., AX (000)). | 通用寄存器:ModR/M 的 reg 域选择通用寄存器(如 AX )。 |
H | The VEX.vvvv field selects a 128-bit XMM or 256-bit YMM register (determined by operand type). For legacy SSE, this operand is destructive. | VEX.vvvv 选择 XMM/YMM:根据操作数类型选择 128/256 位向量寄存器(传统 SSE 编码中为破坏性操作)。 |
I | Immediate data: the operand value is encoded in subsequent bytes of the instruction. | 立即数:操作数值直接编码在指令后续字节中。 |
J | The instruction contains a relative offset to be added to the instruction pointer (e.g., JMP (0E9), LOOP). | 相对偏移:指令包含需加到 RIP 的相对偏移(如 JMP 、LOOP )。 |
L | The upper 4 bits of the 8-bit immediate select a 128-bit XMM or 256-bit YMM register (MSB ignored in 32-bit mode). | 高4位选择 XMM/YMM:8位立即数的高4位选择向量寄存器(32位模式下忽略最高位)。 |
M | The ModR/M byte may refer only to memory (e.g., BOUND, LES, LDS, LSS, LFS, LGS, CMPXCHG8B). | 仅内存操作数:ModR/M 字节仅可指向内存(如 BOUND 、LDS )。 |
N | The R/M field of the ModR/M byte selects a packed-quadword MMX register. | MMX 寄存器:ModR/M 的 R/M 域选择 MMX 寄存器。 |
O | The instruction has no ModR/M byte. The operand offset is coded as a word/dword in the instruction (e.g., MOV (A0–A3)). | 直接偏移:指令无 ModR/M 字节,操作数偏移以字/双字编码(如 MOV AL, [0x1234] )。 |
P | The reg field of the ModR/M byte selects a packed quadword MMX register. | MMX 寄存器(reg 域):ModR/M 的 reg 域选择 MMX 寄存器。 |
Q | ModR/M byte specifies an MMX register or memory address (with segment/base/index/scaling/displacement). | MMX 或内存操作数:ModR/M 指定 MMX 寄存器或内存地址(含段/基址/索引/比例因子/位移)。 |
R | The R/M field of the ModR/M byte may refer only to a general register (e.g., MOV (0F20-0F23)). | 仅通用寄存器:ModR/M 的 R/M 域仅可指向通用寄存器。 |
S | The reg field of the ModR/M byte selects a segment register (e.g., MOV (8C,8E)). | 段寄存器:ModR/M 的 reg 域选择段寄存器(如 MOV ES, AX )。 |
U | The R/M field of the ModR/M byte selects a 128-bit XMM or 256-bit YMM register. | XMM/YMM 寄存器(R/M 域):ModR/M 的 R/M 域选择向量寄存器。 |
V | The reg field of the ModR/M byte selects a 128-bit XMM or 256-bit YMM register. | XMM/YMM 寄存器(reg 域):ModR/M 的 reg 域选择向量寄存器。 |
W | ModR/M byte specifies an XMM/YMM register or memory address (with segment/base/index/scaling/displacement). | XMM/YMM 或内存操作数:ModR/M 指定向量寄存器或内存地址。 |
X | Memory addressed by the DS:rSI register pair (e.g., MOVS, CMPS, OUTS, LODS). | DS:rSI 寻址:由 DS:SI (16位)或 DS:RSI (64位)指向的内存(如字符串指令)。 |
Y | Memory addressed by the ES:rDI register pair (e.g., MOVS, CMPS, INS, STOS, SCAS). | ES:rDI 寻址:由 ES:DI (16位)或 ES:RDI (64位)指向的内存(如字符串指令)。 |
A.2.2 操作数类型编码(Codes for Operand Type)
编码 | 英文说明 | 中文翻译 |
---|---|---|
a | Two one-word operands in memory or two double-word operands, depending on operand-size (BOUND only). | 内存中的双字/字对(仅 BOUND 指令使用)。 |
b | Byte, regardless of operand-size. | 字节(无视操作数大小)。 |
c | Byte or word, depending on operand-size. | 字节或字(依操作数大小而定)。 |
d | Doubleword, regardless of operand-size. | 双字(无视操作数大小)。 |
dq | Double-quadword (128-bit), regardless of operand-size. | 双四字(128位)。 |
p | 32-bit, 48-bit, or 80-bit pointer, depending on operand-size. | 指针(32/48/80位,依操作数大小而定)。 |
pd | 128-bit or 256-bit packed double-precision floating-point. | 压缩双精度浮点(128/256位)。 |
pi | Quadword MMX register (e.g., mm0). | 四字 MMX 寄存器(如 mm0 )。 |
ps | 128-bit or 256-bit packed single-precision floating-point. | 压缩单精度浮点(128/256位)。 |
q | Quadword (64-bit), regardless of operand-size. | 四字(64位)。 |
Quad-quadword (256-bit), regardless of operand-size. | 四四字(256位)。 | |
s | 6-byte or 10-byte pseudo-descriptor. | 伪描述符(6/10字节)。 |
sd | Scalar double-precision floating-point (128-bit). | 标量双精度浮点(128位)。 |
ss | Scalar single-precision floating-point (128-bit). | 标量单精度浮点(128位)。 |
si | Doubleword integer register (e.g., eax). | 双字整数寄存器(如 EAX )。 |
v | Word, doubleword, or quadword (64-bit mode only), depending on operand-size. | 字/双字/四字(64位模式下支持四字)。 |
w | Word (16-bit), regardless of operand-size. | 字(16位)。 |
x | dq or qq based on operand-size. | 双四字或四四字(依操作数大小而定)。 |
y | Doubleword or quadword (64-bit mode only), depending on operand-size. | 双字或四字(64位模式下支持四字)。 |
z | Word for 16-bit operand-size or doubleword for 32/64-bit operand-size. | 字(16位)或双字(32/64位)。 |
上标符号说明(Superscript Symbols)
符号 | 英文说明 | 中文翻译 |
---|---|---|
1A | Bits 5, 4, and 3 of ModR/M byte used as an opcode extension (refer to Section A.4, “Opcode Extensions For One-Byte And Two-byte Opcodes”). | ModR/M 字节的位5/4/3 作为操作码扩展(参考附录A.4节"单/双字节操作码扩展")。 |
1B | Use the 0F0B opcode (UD2 instruction), the 0FB9H opcode (UD1 instruction), or the 0FFFH opcode (UD0 instruction) when deliberately trying to generate an invalid opcode exception (#UD). | 故意触发无效操作码异常(#UD )时,使用 0F0B (UD2)、0FB9H (UD1)或 0FFFH (UD0)操作码。 |
1C | Some instructions use the same two-byte opcode. The ModR/M byte differentiates the instruction (see Table A-6). | 部分指令共享双字节操作码,需通过 ModR/M 字节 区分具体指令(见表A-6)。 |
i64 | The instruction is invalid or not encodable in 64-bit mode. 40-4F (single-byte INC/DEC) become REX prefixes in 64-bit mode (use FE/FF Grp 4/5 for INC/DEC). | 64位模式下无效:40-4F (单字节INC/DEC)在64位模式下变为REX前缀(需改用 FE/FF 组4/5编码INC/DEC)。 |
o64 | Instruction is only available when in 64-bit mode. | 仅64位模式:指令仅在64位模式下可用。 |
d64 | When in 64-bit mode, instruction defaults to 64-bit operand size and cannot encode 32-bit operand size. | 64位默认操作数:64位模式下强制使用64位操作数,不可编码32位。 |
f64 | The operand size is forced to 64-bit in 64-bit mode (operand-size prefixes are ignored). | 强制64位操作数:64位模式下忽略操作数大小前缀,强制使用64位。 |
v | VEX form only exists. No legacy SSE form. For Integer GPR instructions: VEX prefix required. | 仅VEX编码:无传统SSE形式(整数指令必须使用VEX前缀)。 |
v1 | VEX128 & SSE forms only exist (no VEX256), when not inferable from data size. | 仅VEX128/SSE:无VEX256形式(数据大小不可推断时适用)。 |
关键术语说明
- #UD:无效操作码异常(Invalid Opcode Exception)
- REX前缀:x86-64中用于扩展寄存器(如R8-R15)和操作数大小的前缀
- VEX编码:AVX指令集引入的扩展前缀,替代传统SSE前缀(如
66H/F2H
)
在上面的指令组当中,Opcode后面跟着的是,ModR/M,当前指令是不是变长指令就看的这个ModR/M
,那么如何知道指令后面有没有跟ModR/M呢,我们看00对应的是Eb/Gb,我们再接着查文档,E对应的是什么 (A ModR/M byte follows the opcode and specifies the operand. The operand is either a general-purpose register or a memory address (with optional segment/base/index/scaling/displacement).)就是说,后面跟着的是ModR/M,指定寄存器或内存地址(只要看到有E或者G的格式,那么这条指令就是一个变长指令),我们再看下小写d又是什么(Doubleword, regardless of operand-size)表示操作数大小,这样我们就知道了,一个字节的Opcode指令如何查找