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),用于条件分支指令Jcc。提示分支不发生编码为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] | 00 | 000 |
| [ECX] | 001 | |
| [EDX] | 002 | |
| [EBX] | 003 | |
| [--][--] | 004 | |
| disp32 | 005 | |
| [ESI] | 006 | |
| [EDI] | 007 | |
| [EAX]+disp8 | 01 | 000 |
| [ECX]+disp8 | 001 | |
| [EDX]+disp8 | 002 | |
| [EBX]+disp8 | 003 | |
| [--][--]+disp8 | 004 | |
| [EBP]+disp8 | 005 | |
| [ESI]+disp8 | 006 | |
| [EDI]+disp8 | 007 | |
| [EAX]+disp32 | 10 | 000 |
| [ECX]+disp32 | 001 | |
| [EDX]+disp32 | 002 | |
| [EBX]+disp32 | 003 | |
| [--][--]+disp32 | 004 | |
| [EBP]+disp32 | 005 | |
| [ESI]+disp32 | 006 | |
| [EDI]+disp32 | 007 | |
| EAX/AX/AL/MM0/XMM0 | 11 | 000 |
| ECX/CX/CL/MM/XMM1 | 001 | |
| EDX/DX/DL/MM2/XMM2 | 002 | |
| EBX/BX/BL/MM3/XMM3 | 003 | |
| ESP/SP/AH/MM4/XMM4 | 004 | |
| EBP/BP/CH/MM5/XMM5 | 005 | |
| ESI/SI/DH/MM6/XMM6 | 006 | |
| EDI/DI/BH/MM7/XMM7 | 007 | |
| 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] | 00 | 000 |
| [ECX] | 001 | |
| [EDX] | 002 | |
| [EBX] | 003 | |
| 无 | 004 | |
| [EBP] | 005 | |
| [ESI] | 006 | |
| [EDI] | 007 | |
| [EAX*2] | 01 | 000 |
| [ECX*2] | 001 | |
| [EDX*2] | 002 | |
| [EBX*2] | 003 | |
| 无 | 004 | |
| [EBP*2] | 005 | |
| [ESI*2] | 006 | |
| [EDI*2] | 007 | |
| [EAX*4] | 10 | 000 |
| [ECX*4] | 001 | |
| [EDX*4] | 002 | |
| [EBX*4] | 003 | |
| 无 | 004 | |
| [EBP*4] | 005 | |
| [ESI*4] | 006 | |
| [EDI*4] | 007 | |
| [EAX*8] | 11 | 000 |
| [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 |
|---|---|---|---|---|---|---|---|
| 000 | 001 | 002 | 003 | 004 | 005 | 006 | 007 |
| [*]有两种含义: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字节
参考链接
- https://blog.csdn.net/brunomarss/article/details/50589556
- https://blog.csdn.net/sqzxwq/article/details/47786345
OPCode 详解的更多相关文章
- OPCode详解及汇编与反汇编原理
1. 何为OPCode 在计算机科学领域中,操作码(Operation Code, OPCode)被用于描述机器语言指令中,指定要执行某种操作的那部分机器码,构成OPCode的指令格式和规范由处理器的 ...
- 新手入门:史上最全Web端即时通讯技术原理详解
前言 有关IM(InstantMessaging)聊天应用(如:微信,QQ).消息推送技术(如:现今移动端APP标配的消息推送模块)等即时通讯应用场景下,大多数都是桌面应用程序或者native应用较为 ...
- Web端即时通讯技术原理详解
前言 有关IM(InstantMessaging)聊天应用(如:微信,QQ).消息推送技术(如:现今移动端APP标配的消息推送模块)等即时通讯应用场景下,大多数都是桌面应用程序或者native应用较为 ...
- String详解, String和CharSequence区别, StringBuilder和StringBuffer的区别 (String系列之1)
本章主要介绍String和CharSequence的区别,以及它们的API详细使用方法. 转载请注明出处:http://www.cnblogs.com/skywang12345/p/string01. ...
- Linux chmod命令详解
Linux chmod命令详解 chmod----改变一个或多个文件的存取模式(mode) chmod [options] mode files 只能文件属主或特权用户才能使用该功能来改变文件 ...
- PE文件结构详解(四)PE导入表
PE文件结构详解(二)可执行文件头的最后展示了一个数组,PE文件结构详解(三)PE导出表中解释了其中第一项的格式,本篇文章来揭示这个数组中的第二项:IMAGE_DIRECTORY_ENTRY_IMPO ...
- php Zend Opcache,xcache,eAccelerator缓存优化详解及对比
XCACHE XCache 是一个开源的 opcode 缓存器/优化器, 这意味着他能够提高您服务器上的 PHP 性能. 他通过把编译 PHP 后的数据缓冲到共享内存从而避免重复的编译过程, 能够直接 ...
- 详解PHP的执行原理和流程
简介 先看看下面这个过程: • 我们从未手动开启过PHP的相关进程,它是随着Apache的启动而运行的: • PHP通过mod_php5.so模块和Apache相连(具体说来是SAPI,即服务器应用程 ...
- String详解, String和CharSequence区别, StringBuilder和StringBuffer的区别
本章主要介绍String和CharSequence的区别,以及它们的API详细使用方法. 转载请注明出处:http://www.cnblogs.com/skywang12345/p/string01. ...
随机推荐
- GeoServer 查询sql视图
说明: 最近项目中遇到一个需求,需要统计管网的长度,但管网数据量非常大,前端用openlayers接口统计直接就奔溃了. 后尝试使用调后台接口查数据库的方式,虽然可行但是又要多一层与后台交互的工作. ...
- 程序员的算法课(16)-B+树在数据库索引中的作用
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/m0_37609579/article/de ...
- 【Android - 控件】之MD - NavigationView的使用
NavigationView是Android 5.0新特性——Material Design中的一个布局控件,可以结合DrawerLayout使用,让侧滑菜单变得更加美观(可以添加头部布局). Nav ...
- PHP的常用字符串处理
一.拼接字符串 拼接字符串是最常用到的字符串操作之一,在PHP中支持三种方式对字符串进行拼接操作,分别是圆点.分隔符{}操作,还有圆点等号.=来进行操作,圆点等号可以把一个比较长的字符串分解为几行进行 ...
- Haproxy安装部署文档及多配置文件管理方案
一.部署安装 二.软件配置 三.系统服务 四.日志配置 五.小结 文章目录 最近我在负责一个统一接入层的建设项目,涉及到 Haproxy 和 ospf 的运维部署,本文分享一下我在部署 Haproxy ...
- MariaDB和Apache安装
5月24日任务 课程内容: 11.6 MariaDB安装11.7/11.8/11.9 Apache安装扩展apache dso https://yq.aliyun.com/articles/6298a ...
- String引发的提问,我差点跪了
面试官:下面代码执行结果是什么?String t0 = "helloworld";String t1 = new String("helloworld");Sy ...
- 在flink中使用jackson JSONKeyValueDeserializationSchema反序列化Kafka消息报错解决
在做支付订单宽表的场景,需要关联的表比较多而且支付有可能要延迟很久,这种情况下不太适合使用Flink的表Join,想到的另外一种解决方案是消费多个Topic的数据,再根据订单号进行keyBy,再在逻辑 ...
- Linux入侵痕迹检测方案【华为云技术分享】
背景说明 扫描是一切入侵的基础,通过扫描来发现目标主机是否为活动主机.操作系统是什么版本.开放了哪些服务等.扫描技术纷繁复杂,新的扫描技术也层出不穷,不可能穷举所有扫描技术,下面按入侵步骤对主机扫描. ...
- CSS 3D图片翻转 ——3D Flipping Effect
效果: 代码如下: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> < ...