OPCode详解

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

OPCode详解
OpCode
操作码(Operation Code, OPCode):描述机器语⾔指令中,指令要执⾏某种操作的机器码
OPCode在不同的场合中通常具有不同的含义,例如PHP虚拟机(Zend VM)、java虚拟机(JVM)以及⼀些软件保护虚拟机中的最⼩操作单元都可以称之为OPCode。

常⽤字节
常⽤单字节OPCode概览A -- 40~4F
opcode asm using
0x40 inc eax emit(0x40)
0x41 inc ecx emit(0x41)
0x42 inc edx emit(0x42)
0x43 inc ebx emit(0x43)
0x44 inc esp emit(0x44)
0x45 inc ebp emit(0x45)
0x46 inc esi emit(0x46)
0x47 inc edi emit(0x47)
0x48 dec eax emit(0x48)
0x49 dec ecx emit(0x49)
0x4a dec ebx emit(0x4a)
0x4b dec ebx emit(0x4b)
0x4c dec esp emit(0x4c)
0x4d dec ebp emit(0x4d)
0x4e dec esi emit(0x4e)
0x4f dec edi emit(0x4f)
常⽤单字节OPCode概览B -- 50~5F
opcode asm using
0x50 push eax emit(0x50)
0x51 push ecx emit(0x51)
0x52 push edx emit(0x52)
0x53 push ebx emit(0x53)
0x54 push esp emit(0x54)
0x55 push ebp emit(0x55)
0x56 push esi emit(0x56)
0x57 push edi emit(0x57)
0x58 pop eax emit(0x58)
0x59 pop ecx emit(0x59)
0x5a pop edx emit(0x5a)
0x5b pop ebx emit(0x5b)
0x5c pop esp emit(0x5c)
0x5d pop ebp emit(0x5d)
0x5e pop esi emit(0x5e)
0x5f pop edi emit(0x5f)
常⽤单字节OPCode概览C -- 70~7F
opcode asm using
0x70 0x12 Jo 0x12 {_emit(0x70)} {_emit(0x12)}
0x71 ... Jno ... ... ...
0x72 ... Jb ... ... ...
0x73 ... Jae ... ... ...
0x74 ... Je ... ... ...
0x75 ... Jne ... ... ...
0x76 ... Jbe ... ... ...
0x77 ... Ja ... ... ...
0x78 ... Js ... ... ...
0x79 ... Jns ... ... ...
0x7a ... Jp ... ... ...
0x7b ... Jnp ... ... ...
0x7c ... Jl ... ... ...
0x7d ... Jge ... ... ...
0x7e ... Jle ... ... ...
0x7f ... Jg ... ... ...
常⽤单字节OPCode概览D -- 90~9F
Opcode asm Using
0x90 Nop/xchg eax,eax _emit(0x90)
0x91 Xchg eax,ecx
0x92 Xchg eax,edx
0x93 Xchg eax,ebx
0x94 Xchg eax,esp
0x95 Xchg eax,ebp
0x96 Xchg eax,esi
0x97 Xchg eax,edi
OPCode与指令的对应关系
同类型的指令OPCode不⼀定相同
B8 01000000 mov eax, 1
8B C3 mov eax, ebx
8B C7 mov eax, edi
OPCode相同的情况下指令也不⼀定相同
90 nop
90 xchg ax, ax
90 xchg eax, eax
结论: OPCode与汇编指令并⾮是单纯的对应关系
那么它是如何进⾏解释的呢?
⾸先它分为6个主要数据域,其中只有代码是必须存在的,指令长度在1-16个字节
所以指令独此⼀份,不可能为其他机器码
x86与x86-64指令集的指令的格式为:
指令前缀指令码ModR/M SIB偏移直接数Instruction Prefixes Opcode Displacement Immediate
可选。

最多4个单字节前缀。

任何顺序均可。

单字节、双字
节、三字节
按需。

0-2位:R/M 3-5位:
Reg/Opcode 6-7位:Mod
按需。

0-2位:Base 3-5位:
Index 6-7位:Scale
0、1、2、4
字节长
0、1、
2、4字节

1,指令前缀Instruction Prefixes
分为4组,每组⽤1个字节编码。

每组在指令中⾄多指定1个前缀值。

4组的顺序可以任意。

第1组锁与重复(Lock and repeat)
锁(LOCK)编码为:F0H。

⽤于互斥访问共享内存的操作。

⾮零时重复(REPNE/REPNZ)编码为:F2H。

⽤于字符串操作指令。

为零时重复(REP/REPE/REPZ)编码为:F3H。

⽤于字符串操作指令。

第2组
段覆盖(Segment override):CS、SS、DS、ES、FS、GS的段覆盖前缀的编码分别是2EH、36H、3EH、26H、64H、65H.
分⽀提⽰(Branch hints),⽤于条件分⽀指令J cc。

提⽰分⽀不发⽣编码为2EH;提⽰分⽀发⽣编码为3EH。

第3组操作数长度覆盖(Operand-size override)编码为66H。

⽤于在16位与32位操作数切换。

第4组地址长度覆盖(Address-size override)编码为67H.⽤于在16位与32位地址切换。

;切换操作数⼤⼩
;切换顺序: 从⼤到⼩
40 INC EAX
66 40 INC AX
;⽆效的前缀应⽤
8AC1 MOV AL, CL
66 BAC1 MOV AL, CL
;重复操作段前缀
F3 66 AD REP LODSW
F2 AC REPNE LODSB
;段超越前缀
8B 03 MOV EAX, [DWORD DS:EBX]
658B 03 MOV EAX, [DWORD GS:EBX]
前缀的具体含义可以在Intel⼿册中查到,⽐如2E,从⼿册可以看出是锁定CS段
2,代码code
长度为1、2或3字节,此外ModR/M中还可能有3位。

对于双字节指令码或三字节指令码,其中的第1个字节为0FH,⽤于与指令前缀区分。

3,构造模式ModR/M
构造模式(Mode): 主要解析逻辑集中在ModeR/M域,通过查找Intel⼿册解析该域确定指令的具体格式
分为三个部分
模式Mode
寄存器Reg
寄存器R/M
对照Intel⼿册中的表来解析OPCode中的ModR/M域来确定指令的具体格式.
89 D8 mov eax, ebx
D8 = 11011000
Mod Reg R/M
11 011 000
许多指令的内存操作数需要使⽤ModR/M字节作为寻址模式说明符。

其中的mod与r/m组合,共有32个值,表⽰8个寄存器与24种寻址模式。

reg/opcode表⽰寄存器号或者额外的3位指令码,其具体含义依赖基本指令码。

Mod与R/M的5位表⽰的第⼀操作数(源与⽬的操作数中寻址⽅式更复杂的那个操作数,指令码中的“⽅向位”direction bit(d)给出源或⽬的操作数哪个是第⼀操作数)的寻址⽅式如下:
寻址⽅式Mod R/M
[EAX]00000
[ECX]001
[EDX]002
[EBX]003
[--][--]004
disp32005
[ESI]006
[EDI]007
[EAX]+disp801000
[ECX]+disp8001
[EDX]+disp8002
[EBX]+disp8003
[--][--]+disp8004
[EBP]+disp8005
[ESI]+disp8006
[EDI]+disp8007
[EAX]+disp3210000
[ECX]+disp32001
[EDX]+disp32002
[EBX]+disp32003
[--][--]+disp32004
[EBP]+disp32005
[ESI]+disp32006
[EDI]+disp32007
EAX/AX/AL/MM0/XMM011000
ECX/CX/CL/MM/XMM1001
EDX/DX/DL/MM2/XMM2002
EBX/BX/BL/MM3/XMM3003
ESP/SP/AH/MM4/XMM4004
EBP/BP/CH/MM5/XMM5005
ESI/SI/DH/MM6/XMM6006
EDI/DI/BH/MM7/XMM7007
1.[--][--]表⽰随后的SIB字节指明寻址⽅式;
2.Mod为11B时,表⽰寄存器操作数。

对于R/M的每个值,根据指令码与操作数长度属
性确定具体的寄存器号。

3.当指令需要第2操作数时,由Reg/Opcode的3位给出。

第2操作数只能是寄存器操作数。

寄存器的指定
⽅式,与Mod为11B时指定作为第1操作数的寄存器的⽅式完全相同。

某些ModR/M字节表⽰的寻找模式,需要SIB字节来补充寻址⽅式。

scale表⽰⽐例系数;index表⽰变址寄存器号;base表⽰基址寄存器号。

使⽤scale与index的5位定义⽐例变址寄存器如下:
4,辅助分析SIB
分为三个部分:
⽐例Scale
索引IndexOf
基数Base
⽐例变址基数Index
[EAX]00000
[ECX]001
[EDX]002
[EBX]003
⽆004
[EBP]005
[ESI]006
[EDI]007
[EAX*2]01000
[ECX*2]001
[EDX*2]002
[EBX*2]003
⽆004
[EBP*2]005
[ESI*2]006
[EDI*2]007
[EAX*4]10000
[ECX*4]001
[EDX*4]002
[EBX*4]003
⽆004
[EBP*4]005
[ESI*4]006
[EDI*4]007
[EAX*8]11000
[ECX*8]001
[EDX*8]002
[EBX*8]003
⽆004
[EBP*8]005
[ESI*8]006
[EDI*8]007
3位base表⽰的基址寄存器号,定义如下:
EAX ECX EDX EBX ESP[*]ESI EDI
000001002003004005006007 [*]有两种含义:1.如果Mod为00B,则[scaled index] + disp32,即没有基址寄存器。

2.如果Mod为01B或
10B,表⽰基址寄存器为EBP。

在汇编程序设计中,⼀般把第1操作数的寻址⽅式总结为如下8种:
寻址⽅式英⽂术语举例
⽴即(数)寻址immediate addressing mov EAX, 01F2H
寄存器寻址register addressing mov EAX, ESI
直接寻址direct addressing mov EAX, DWORD PTR [1FFA00H]
寄存器间接寻址register indirect addressing mov EAX, DWORD PTR [EBX]
基址加变址寻址base-plus-index addressing mov EAX, DWORD PTR [EBX+ESI]
寄存器相对寻址或基址相对寻址register relative addressing mov EAX, DWORD PTR [EDI+01F4H]基址相对加变址寻址base relative-plus-index addressing mov EAX, DWORD PTR 01F4H[EDI+EBX]⽐例变址寻址scaled-index addressing mov EAX, DWORD PTR 01F4H[EDI*8+EBX]
综合指令格式中的ModR/M与SIB两个字节的语义规定,指令的第1操作数的寻址⽅式可总结为4种物理实现:
⽴即数:表⽰在指令的“⽴即数”部分。

包括了直接寻址,即⽴即数作为内存的地址。

寄存器操作数:Mod为11B,根据R/B部分的值、指令码、操作数长度属性,确定具体的寄存器号。

基址相对寻址:即[Reg+disp8或disp32]。

包括了寄存器间接寻址。

这种情况计算第1操作数地址时使⽤了1个寄存器。

基址加⽐例变址的相对寻址:即[BaseReg+IndexReg*scale+disp8或disp32]。

这种情况计算第1操作数地址时使⽤了2个寄存器。

5,位移Displacement
6,⽴即数Immediate
⼿⼯在Intel⼿册中查找OPCode的汇编代码:
F0: 26: C78491 AA000000 11000000
F0: 26: C7 84 91 AA000000 11000000
锁定前缀段超越 OPCode ModeR/M SIB 偏移⽴即数
查找前缀
F0 - Prefixes:锁定前缀,即 Lock
26 - Prefixes:修改默认段,即段超越前缀,查"Opcode Map"如图,段超越前缀为 ES
查找Code
C7 - Code:查"Opcode Map"如图,可知:Grp 11 MOV Ev,Iz
查找ModeR/M
84 - ModR/M:转为⼆进制 10 000 100
模式(Mod)段:2位 10
寄存器(Reg)段:3位 000
寄存器(R/M)段:3位 100
查"ModR/M"表如图,得到 [..][..]+disp32
查找SIB
91 - SIB:转为⼆进制 10 010 001
⽐例(Scale)段:2位 10
索引(Index)段:3位 010
基数(Base)段:3位 001
查"SIB"表如图,可知 [EDX*4]+ECX
AA000000 - Displacement:此为⼩端模式,即为 0xAA
11000000 - Immediate:⼩端模式,即为 0x11
综上,得到:
LOCK MOV ES:[EDX4+ECX+0xAA],0x11
即为:
LOCK MOV DWORD PTR ES:[EDX4+ECX+0x0AA],0x11
3、内联汇编
;内联汇编可以有两种形式,⼀种是⾏内联汇编,⼀种是块内联汇编,⼆者可交叉使⽤;
;⾏内联汇编:
__asm mov eax,a
__asm add eax,b
__asm mov c,eax
; 块内联汇编:
__asm{
mov eax,a
add eax,b
mov c,eax
}
4、裸函数
// ;定义:没有任何可执⾏代码的空函数,在内存中仅仅是⼀条地址信息.
// ; 使⽤关键字“__declspec(naked)”定义;
// ; 例:
void __declspec(naked) TestFun( ){
__asm ret
}
总结:
ModR/M信息与确认是否有SIB字节
当Mod != 11b并且R/M的值为100b的时候,表⽰指令后续有SIB字节,并且该内存操作对象由SIB编码。

MODR/M⾥有三种情况会有SIB字节
参考链接
1.
2.。

相关文档
最新文档