OPCode 详解
Posted songyaqi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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个字节
所以指令独此一份,不可能为其他机器码
1, 前缀 Prefixes
前缀(Prefixes):大小1Byte,描述指令前缀情况,换分为5个集合,一个OPCode可能有几个Prefixes
- 66 切换操作数的大小
- 67 切换地址的大小
- F2/F3 重复操作前缀
- 2E/36/3e/26/64/65 修改默认段(段超越前缀)
- F0 锁定前缀
;切换操作数大小
;切换顺序: 从大到小
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
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
4,辅助分析 SIB
分为三个部分:
- 比例
Scale
- 索引
IndexOf
- 基数
Base
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:[EDX*4+ECX+0xAA],0x11
即为:
LOCK MOV DWORD PTR ES:[EDX*4+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字节
参考链接
- https://blog.csdn.net/brunomarss/article/details/50589556
- https://blog.csdn.net/sqzxwq/article/details/47786345
以上是关于OPCode 详解的主要内容,如果未能解决你的问题,请参考以下文章