JVM---汇编指令集
apt install radar2
rasm2 -L #查看architectures
rasm2 -a x86 -b 32 'mov eax, 33' #转机器码
echo 'push eax;nop;nop' | rasm2 -f -
rasm2 -a x86 -d 55 #转汇编 push ebp
rasm2 -L #列出架构
rasm2 -a x86 -b 32 'mov eax, 33' #汇编
rasm2 -a x86 -b 32 -d '90' #反汇编
rasm2 -a riscv -d b70701001307a00ab7366e01
lui a5, 0x10
li a4, 170
lui a3, 0x16e3
radar2当前不支持 riscv 的反汇编 rasm2 -a riscv "lui a5, 0x10" 会报错
root@hasee-pc:~# rasm2 -a x86 -d 8b07
mov eax, dword [edi]
root@hasee-pc:~# rasm2 -a x86 -d 2e8b07
mov eax, dword cs:[edi]
root@hasee-pc:~# rasm2 -a riscv -d 4040
lw s0, 4(s0)
root@hasee-pc:~# rasm2 -a x86 -d 52f30f1005062e00005049
push edx
movss xmm0, dword [0x2e06]
push eax
dec ecx
指令 不要拘泥于 字节 8位的概念. 指令中的 每一个bit 都有其意义... (good) 例如
risc-v 32位 指令划分域的时候, 7bit 3bit 5bit 12bit...等为一组...
R 型指令
I型指令
L型指令
指令执行
分支跳转指令
Opcode 对指令提供操作码,ModRM 最主要作用是对指令的 operands 提供寻址,另一个作用是对 Opcode 进行补充,而 SIB 则是对 ModRM 进行补充寻址
有两种情况下是无需用 ModRM 提供寻址的:
(1)一部分操作数是寄存器的,它直接嵌入 Opcode 中。
(2)一部分操作数是立即数的,它直接嵌入指令编码中。
2.3 ModR/m说明 https://cloud.tencent.com/developer/article/1444066
ModR/m
里面分为三部分
Mod 表示寄存器的寻址方式.
Reg/opcode 表示寄存器或者OpCode的编码
R/M 表示汇编中第一个寄存器的编码.
Mod 代表寻址方式 2位表示
00 寄存器间接寻址
01 寄存器相对寻址偏移
10 寄存器先对寻址偏移
11 寄存器直接寻址
其它寻址方式放在SIB里面
Reg/Opcode 代表指令,
如 mov [ebp - 38h],eax. 那么就代表eax的编号
有时候表示寄存器,有时候表示Opcode
R/M 表示汇编的第一个寄存器
如 mov[ebp - 38h],eax 代表的是ebp
2.4 SIB说明
SIB 占一个字节.可能有可能没有,是对ModR/M寻址的补充.
一条汇编指令
实现自己的指令集
https://blog.csdn.net/qq_36320285/article/details/84335674
wl 原来在前缀 prefix里 ..
ModR/M,SIB编码的含义
让我们从最经常用到的域开始学起——ModR/M。
在开始之前,先来讲一些最基础的概念。
一个字节如果被转换成二进制,则是由8位(bit)来表示(不足8位的话则高位用0来补足),
例如:16进制 2进制
B7 1011 0111 3A 0011 1010
示例中的B7的二进制是1011 0111,
这是典型的4:4表示格式——1011表示的是B,0111表示的是7,
这样,1011 0111表示的就是B7了。
那么我们可不可以用另外一种方式来表示一个字节呢?
答案是肯定的:16进制 2进制的4:4格式
2进制的2:3:3格式
B7 1011 0111 10 110 111 3A 0011 1010 00 111 010 请看,
我们在这里引进了一种新的表示格式:2:3:3它的特点是把一个字节的8位二进制分成3个部分:
最高的2位表示的是一个东西,接下来的3位表示的是另外一个东西,
以及最后的3位表示的是另另外一个东西。
好了,明白了这一点后,我们来开始吧!
首先回忆一下OpCode的组成格式:Prefixes code ModR/M SIB Displacement Immediate
请注意第三项:ModR/M,它占一个字节,其格式为:7 6 5 3 2 0 Mod Reg/Opcode R/M 可见,ModR/M是由Mod、Reg/Opcode和R/M三个部分组成的。
每个部分所占的bit大小为: Mod: 占最高位的6~7共2个bit
Reg/Opcode: 占中间位的3~5共3个bit
R/M: 占最低位的0~2共3个bit
呵呵,正好是2:3:3的格式!
ModR/M的具体描述如下面两个表,第一个是16位的,第二个是32位的:(截图自《IA-32 Intel Architecture Software Developer's Manual Volume 2: Instruction Set Reference》,页码2-5,2-6)- 16位 -- 32位 -
让我们来举个例子看看ModR/M到底是怎么来看的:
mov edi, ecx 8B F9 sub edi, ecx 2B F9
注意这两个OpCode的第二个字节——都是F9,再来看看OpCode的格式:Prefixes Code ModR/M SIB Displacement Immediate 我们在前面说过,在OpCode的格式中,只有Code是必须有的,别的都是可选的。
所以,在8B F9和2B F9这两组OpCode中,8B和2B就是Code,
(这里没有Prefixes,因为Prefixes只有在前面的章节中所介绍过的那几个:66、67、F2、F3、2E、36、3E、26、64、65、F0)。
紧接着在Code后面的就是ModR/M了,所以在这两组OpCode中的F9就是ModR/M。(在这里也没有SIB、Displacement和Immediate)
F9的4:4格式的二进制是1111 1001,我们把它分解成2:3:3的二进制看看:
16进制 2进制的2:3:3格式 F9 11 111 001 也就是:
Mod: 11
Reg/Opcode: 111
R/M: 001
假设是在32位模式下。从上面的第二个图中可以看到,Mod总共分为00、01、10、11四种情况,每种情况又分别有8种情况。现在Mod是11,所以我们应该看Mod为11的那一栏。
OK,现在来讨论第二个:Reg/OpcodeReg/Opcode中间的那个“/”表示“或”,意思就是,这个地方可以表示为Reg或者Opcode——至于到底什么时候表示Reg,什么时候表示Opcode,这就要由Code来决定了。目前我们不必去深究它,后面会讲明白的,我们只要知道,如果它是表示Opcode,则这个指令必定是2个字节的。
Reg由3个bit的二进制组成,因此,它可以表示:2 ^ 3 = 8 一共8种可能的值。我们知道,常用的通用寄存器恰好也有8个,
因此,根据组合数学的常识,可以得到:REG && Register REG Register 000 EAX 001 ECX 010 EDX 011 EBX 100 ESP 101 EBP 110 ESI 111 EDI 这是在32位的模式下得到的。
在16位的模式下,Reg则是表示另外一种“局部”的格式,它的低4位表示寄存器的低地址,高4位表示寄存器的高地址,
如下表:REG && Register REG Register 000 AL 001 CL 010 DL 011 BL 100 AH 101 CH 110 DH 111 BH 好了,把目光返回到上面的32位ModR/M图,看看最上面,在r32(/r)那一栏中,REG=111表示的就是寄存器EDI到目前为止,最后剩下还没讨论的就是R/M。
这一栏要与Mod结合起来。我们来看Mod为11的那一栏——R/M为001对应的寄存器是ECX好了!大功告成!
整理如下: Mod: 11 表示应该查看Mod为11的那一栏 Reg/Opcode: 111 表示的是寄存器EDI R/M: 001 表示的是ECX 因此,通过OpCode:8B F9 2B F9 不难得到:mov edi, ecx 8B F9 sub edi, ecx 2B F9
(注:8B是助记符“MOV”的Code,2B是助记符“SUB”的Code)
x86指令解析较好的
displacement 规则 由 mod/r 来确定
解析变长指令 规则
x86前缀 目前只有固定的11个
呵呵不要紧,让我们来举个例子看看ModR/M到底是怎么来看的:
mov edi, ecx 8B F9
sub edi, ecx 2B F9
注意这两个OpCode的第二个字节——都是F9,再来看看OpCode的格式:
Prefixes Code ModR/M SIB Displacement Immediate
我们在前面说过,在OpCode的格式中,只有Code是必须有的,别的都是可选的。所以,在8B F9和2B F9这两组OpCode中,8B和2B就是Code,(这里没有Prefixes,因为Prefixes只有在前面的章节中所介绍过的那几个:66、67、F2、F3、2E、36、3E、26、64、65、F0)。
紧接着在Code后面的就是ModR/M了,所以在这两组OpCode中的F9就是ModR/M。(在这里也没有SIB、Displacement和Immediate)
F9的4:4格式的二进制是1111 1001,我们把它分解成2:3:3的二进制看看:
16进制 2进制的2:3:3格式
F9 11 111 001
也就是:
Mod: 11
Reg/Opcode: 111
R/M: 001
晕头转向了?呵呵,让我们来对其分而治之吧!
Practice Makes Perfect!
怎么判断是不是前缀指令呢?
前缀指令就几个,很好确定,根据指令的内容来确定
2、前缀指令是分组的:
前缀指令最多是4个,每组一个
<1>LOCK 和REPEAT前缀指令:
LOCK F0 //锁地址总线的 在同一时刻只能有一个核的CPU来读取那条指令,这个指令在多核下才有意义
REPNE/REPNZ F2 //重复执行 当zf是0的时候执行
REP/REPZ F3 //重复执行 当zf是1的时候执行
<2>段前缀指令:
CS(2E)、SS(36)、DS(3E)、ES(26)、FS(64)、GS(65) //存在的意义是可以改变寻址时候的段寄存器
<3>操作数宽度前缀指令: //操作数的宽度默认是32位,加上66,操作数的宽度就编程了16位
66 //操作数的宽度默认是16位,加上66,操作数的宽度就编程了32位
**<4>地址宽度前缀指令: ** //改变寻址方式的 ,这个前缀指令也是双向的
67
3、前缀指令最多占4个字节,最少占0个字节
每组最多一个,可以组合使用,没有顺序问题
Intel汇编指令格式解析
环境:
win7_x64旗舰版、VS2015企业版
一、Intel保护模式、实地址模式和虚拟8086模式指令格式(x86)
图在Intel手册Volume2 2.1章节
1.1)Instruction Prefixes:指令前缀,可选项,每个前缀一个字节,可选0个前缀到4个不等;指令前缀分为四组,每组都允许设置指定的前缀代码。
Group 1:锁定和重复前缀。
Group 2:段覆盖前缀。
Group 3:操作数大小覆盖前缀。
Group 4:地址大小覆盖前缀。
1.2)Opcode:操作码,这是唯一不可省略的项,1、2或3个字节,在某些情况下会有额外的三个位作为补充opcode,这三个位是ModR/M中的Reg/Opcode域。
1.3)ModR/M:一共有三个域,Mod,Reg/Opcode, R/M,具体编码格式参考Op/En列。
Reg/Opcode在特定情况下作为Opcode的补充操作码,特定情况下作为第一个或第二个操作数寄存器。
MOV opcode:
MOV Op/En:
对于89 /r,Op/En为MR,Reg/Opcode表示第二个操作数Operand2寄存器。
而对于8B /r,Op/En为RM,Reg/Opcode则表示第一个操作数Operand1寄存器。
Mod字段与R/M字段组合形成32个可能的值:八个寄存器和24个寻址模式。
Reg/Opcode字段指定一个寄存器或三位操作码信息。Reg/Opcode字段的用途在主操作码中指定。
R/M字段可以为存器指定操作数,也可以将其与Mod字段组合形成编码寻址模式。有时,Mod字段和R/M字段的某些组合用于表示某些指令的操作码信息。
ModR/M字节的某些编码需要第二个寻址字节(SIB字节),32位寻址的base-plus-index和scale-plus-index形式需要SIB字节。SIB字节包括以下字段:
"scale"字段指定比例因子。
"index"字段指定索引寄存器的寄存器索引
"base"字段指定基本寄存器的寄存器索引
有关ModR/M和SIB字节的编码,请参见第2.1.5节
1.4)SIB:定义ModR/M的寻址方式的补充寻址方式,使用"Base + Scaled Index"格式。
1.5)Displacement:偏移,可选,0,1,2,4个字节。
1.6)Immediate:立即数,可选,0,1,2,4个字节。
二、IA-32e模式指令格式(x64)
图在Intel手册Volume2 2.2.1章节
2.1)IA-32e模式有两个子模式
Compatibility Mode:使64位操作系统能够不加修改地运行大多数传统保护模式软件。
64-Bit Mode:使64位操作系统能够运行为访问64位地址空间而编写的应用程序。
2.2)REX Preflx
REX前缀是在64位模式下使用的指令前缀字节,与x86模式的不同之处就是多了这个REX Preflx,其他基本与x86相同。它有以下作用:
指定GPRs和SSE寄存器
指定64位操作数大小
指定扩展寄存器
并非所有指令都需要64位模式下的REX前缀。 仅当一条指令引用扩展寄存器之一或使用64位操作数时,才需要前缀。 如果在没有含义的情况下使用REX前缀,则将其忽略。
三、使用ModR/M字节的32位寻址
图在Intel手册Volume2 2.5.1章节Addressing-Mode Encoding of ModR/M and SIB Bytes
解释:
3.1)[--][--]:表示使用SIB结构。
3.2)disp32:表示32位偏移。
3.3)[--][--]+disp8:表示使用SIB结构,且SIB结构后面有一个8位的偏移。
3.4)[--][--]+disp32:表示使用SIB结构,且SIB结构后面有一个32位的偏移。
|
ModR/M.mod
|
寻址模式
|
描述
|
|
00
|
[base]
|
提供 [base] 形式的 memory 寻址
|
|
01
|
[base + disp8]
|
提供 [base + disp8] 形式的 memory 寻址
|
|
10
|
[base + disp32]
|
提供 [base + disp32] 形式的 memory 寻址
|
|
11
|
register
|
提供 register 寻址。
|
四、使用SIB字节的32位寻址
图在Intel手册Volume2 2.5.1章节Addressing-Mode Encoding of ModR/M and SIB Bytes
SIB结构使用"Base + Scaled Index"格式。
Base的可选值为:Scaled Index的可选值为:none、[REG]、[REG2]、[REG4]、[REG*8],REG为实际的某个寄存器。
none表示没有Scaled Index,即Scaled Index的为0。
[REG]表示使用一个寄存器如[EAX]、[ECX]和[EDX]等等。
[REG2]表示使用寄存器乘以2如[EAX2]、[ECX2]和[EDX2]等等。
五、MOVE-Move指令格式
图在Intel手册Volume2 4.3章节MOV-Move小节
解释:
5.1)r:寄存器,r8表示8位寄存器,r16表示16位寄存器,r32和r64依次类推。
5.2)m:内存地址,m8表示8位地址,m16表示16位地址,m32和m64依次类推。
5.3)r/m:寄存器或内存
5.4)/r:表示操作码有ModR/M结构,且ModR/M结构的Reg/Opcode域为Reg,表示第二个操作码寄存器。
5.4)REX:表示该操作码有REX Preflx字段。
5.5)REG.W:表示该操作码有REX Preflx字段且W位值为1。
5.6)rb:表示使用byte寄存器,即8位寄存器。
5.7)ib:表示使用byte立即数,即8位立即数。
5.8)rw:表示使用word寄存器,即16位寄存器。
5.9)iw:表示使用word立即数,即16位立即数。
5.10)rd:表示使用dword寄存器,即32位寄存器。
5.11)id:表示使用dword立即数,即32位立即数。
5.12)/数字:数字在0-7之前,例如/0或/7,表示指定有ModR/M选项,且只使用r/m,reg字段包含提供指令操作码扩展名的数字,例如/4表示reg字段为100B。
完整解释请看Intel手册Volume2第3.1.1.1章节Opcode Column in the Instruction Summary Table (Instructions without VEX Prefix)
六、ADD-Add指令格式
图在Intel手册Volume2 3.2章节ADD-Add小节
七、MOVSX/MOVSXD指令格式
图在Intel手册Volume2 4.3章节MOVSX/MOVSXD—Move with Sign-Extension小节
八、JMP—Jump指令格式****
********
解释:
|
代码
|
指令
|
说明
|
|
EB cb
|
JMP rel8
|
相对短跳转,位移量相对于下一条指令,跳转地址为RIP + 2 + rel8
|
|
E9 cw
|
JMP rel16
|
相对近跳转,位移量相对于下一条指令,跳转地址为RIP + 3 +rel16
|
|
E9 cd
|
JMP rel32
|
相对近跳转,位移量相对于下一条指令,跳转地址为RIP + 5 + rel32
|
|
FF /4
|
JMP r/m16
|
绝对间接近跳转,地址由 r/m16 给出
|
|
FF /4
|
JMP r/m32
|
绝对间接近跳转,地址由 r/m32 给出
|
|
FF /4
|
JMP r/m64
|
绝对间接近跳转,地址由 r/m64 给出,跳转地址为*(REG + r/m64),/4表示Reg/Opcode为100B
|
|
EA cd
|
JMP ptr16:16
|
绝对远跳转,地址由操作数给出
|
|
EA cp
|
JMP ptr16:32
|
绝对远跳转,地址由操作数给出
|
|
FF /5
|
JMP m16:16
|
绝对间接远跳转,地址由 m16:16 给出
|
|
FF /5
|
JMP m16:32
|
绝对间接远跳转,地址由 m16:32 给出
|
****8.1)示例(x64环境)****
*0x0000000000405f10 ff 25 32 52 20 00 jmpq 0x205232(%rip)
属于FF /4 JMP r/m64,跳转地址为=*(rip + 0x205232),其中ModR/M=0x25=00100101B,Mod=00B,Reg/Opcode=/4=100B,R/M=101
******0x0000000000408f97 ff a0 17 00 00 ac jmpq *-0x53ffffe9(%rax)******
属于FF /4 JMP r/m64,跳转地址为=*(rax + 0xac000017),其中ModR/M=0xa0=10100000B,Mod=10B,Reg/Opcode=/4=100B,R/M=000
*0x0000000000408fbf ff a8 05 00 00 0a ljmpq 0xa000005(%rax)
属于FF /5 JMP m16:32,跳转地址为=*(rax + 0x0a000005),其中ModR/M=0xa8=10101000B,Mod=10B,Reg/Opcode=/5=101B,R/M=000
九、与之相关的注册码
完整解释请看Intel手册Volume2 第3.1.1.1章节Opcode Column in the Instruction Summary Table (Instructions without VEX Prefix)
在64位模式下,使用RAX/RCX/RDX/RBX/RSP/RBP/RSI/RDI不需要REX Prefix,而使用R8 ~ R15则是必须的
十、示例代码分析
10.1)示例一(x86环境)
012E17DD 8B 45 EC mov eax,dword ptr [ebp-14h]
解析mov eax,dword ptr [ebp-14h]的机器代码:
eax为32位寄存器,[ebp-14h]是一个内存地址,所以指令应该是"MOV r32,m32",根据第五节 MOVE-Move指令格式,符合条件的只有
通过8B /r进行分析
Instruction Prefixes:该操作码没有Instruction Prefixes。
Opcode:操作码为8B。
ModR/M:/r表示操作码有ModR/M结构,且ModR/M结构的Reg/Opcode域为Reg,表示第一个操作码寄存器。
第一个操作码寄存器为eax,根据第三节 ModR/M字节的32位寻址表,Reg域为000,[ebp-14h]是相对寄存器寻址,所以Mod域为01,R/M域为101,最后的ModR/M为01 000 101,即45H。
SIB:无。
Displacement:相对ebp寄存器的偏移为-14h,-14h的源码为0001 0100,反码为1110 1011,补码为1110 1100,即EC。
Immediate:无。
最后的机器码为:8B 45 EC。
10.2)示例二(x86环境)
012E17E3 89 45 EC mov dword ptr [ebp-14h],eax
解析mov dword ptr [ebp-14h],eax的机器代码:
[ebp-14h]是一个内存地址,eax为32位寄存器,所以指令应该是"MOV m32,r32",根据第五节 MOVE-Move指令格式,符合条件的只有
通过89 /r进行分析
Instruction Prefixes:该操作码没有Instruction Prefixes。
Opcode:操作码为89H。
ModR/M:/r表示操作码有ModR/M结构,且ModR/M结构的Reg/Opcode域为Reg,表示第二个操作码寄存器。
第二个操作码寄存器为eax,根据第三节 ModR/M字节的32位寻址表,Reg域为000,[ebp-14h]是相对寄存器寻址,所以Mod域为01,R/M域为101,最后的ModR/M为01 000 101,即45H。
SIB:无。
Displacement:相对ebp寄存器的偏移为-14h,-14h的源码为0001 0100,反码为1110 1011,补码为1110 1100,即EC。
Immediate:无。
最后的机器码为:89 45 EC。
10.3)示例三(x86环境)
012E17E6 01 04 8E add dword ptr ds:[esi+ecx4],eax*
解析add dword ptr ds:[esi+ecx*4],eax的机器代码:
[esi+ecx*4]是一个内存地址,eax为32位寄存器,所以指令应该是"ADD m32,r32",根据第五节 ADD-Add指令格式,符合条件的只有
通过01 /r进行分析
Instruction Prefixes:该操作码没有Instruction Prefixes。
Opcode:操作码为01H。
ModR/M:/r表示操作码有ModR/M结构,且ModR/M结构的Reg/Opcode域为Reg,表示第二个操作码寄存器。
第二个操作码寄存器为eax,根据第三节 ModR/M字节的32位寻址表,Reg域为000,[esi+ecx*4]是寄存器间接寻址且且使用SIB结构
所以Mod域为00,R/M域为100,最后的ModR/M为00 000 100,即04H。
SIB:根据[esi+ecx*4],SS为10,Index为001,r32为esi寄存器即110,所以SIB为10 001 110 = 8EH。
Displacement:无。
Immediate:无。
最后的机器码为:01 04 8E。
10.4)示例四(x64环境)
000000013F3D1212 48 63 4C 24 20 movsxd rcx, dword ptr [esp+20h]
解析movsxd rcx, dword ptr [esp+20h]的机器代码:
rcx为64位寄存器,[esp+20h]是一个内存地址,esp为32位寄存器,内存地址是32位地址,所以指令应该是"movsxd r64,mr32",根据第七节 MOVSX/MOVSXD—Move with Sign-Extension指令格式,符合条件的只有
通过REX.W + 63 /r进行分析
Legacy Prefixes:无。
REX Prefixes:REX.W表示操作码有REX Prefixes结构,且W位为1,则REX Prefixes为 0100 1000,即48H。
Opcode:操作码为63H。
ModR/M:/r表示操作码有ModR/M结构,且ModR/M结构的Reg/Opcode域为Reg,表示第一个操作寄存器。
第一个操作寄存器为rcx,根据第三节ModR/M字节的32位寻址表,Reg域为001,[esp+20h]是相对寄存器寻址,所以Mod域为01,表中找不到esp寄存器,所以R/M域为100。
最后的ModR/M为01 001 100,即4CH。
SIB:根据[--][--]+disp8可以看出,一定有SIB结构,SIB结构为"Base + Scaled Index",[esp+20h]没有Scaled Index,所以SS为00,Index为100,Base为esp寄存器即100,最后SIB为00 100 100 = 24H。
Displacement:相对esp寄存器的偏移为+20h,+20h的补码为0010 0000,即20H。
Immediate:无。
最后的机器码为:48 63 4C 24 20。
参考:
1)[原创]X86汇编之指令格式解析:https://bbs.pediy.com/thread-191802.htm
2)[原创]X64汇编之指令格式解析:https://bbs.pediy.com/thread-206780.htm
3)X86指令编码内幕 --- 指令格式:https://blog.csdn.net/xfcyhuang/article/details/6228030
4)Intel硬编码(一):Opcode Map、定长指令与指令前缀:https://blog.csdn.net/apollon_krj/article/details/77524601
5)Intel硬编码(二):不定长指令、ModR/M与SIB详解(基于P6微架构):https://blog.csdn.net/apollon_krj/article/details/77524601
6)英特尔指令参考手册:https://www.felixcloutier.com/x86/
7)英特尔64与IA-32体系结构软件开发人员手册:https://software.intel.com/en-us/download/intel-64-and-ia-32-architectures-sdm-combined-volumes-1-2a-2b-2c-2d-3a-3b-3c-3d-and-4
8)英特尔64与IA-32体系结构优化参考手册:https://software.intel.com/sites/default/files/managed/9e/bc/64-ia-32-architectures-optimization-manual.pdf
手头不方便的时候,看到自己喜欢的东西无妨采取 “ 过我眼者即为我有 ” 得之我幸,失之我命 ” 心态。
指令的第一字节决定了指令的类型,并且,也是由第一字节决定了,是否还要继续取第2或第3字节。
指令的翻译主要是针对第1字节(51的指令只有256条),后面1或2字节是数据或地址。可以根据第1字节的类型,相应处理第2或第3字节。
指令译码一般有几个过程(部件):指令预取、指令预分析(预解码)、解码。预取是从cache或者内存取一系列的字节(大小可以保证至少包含一条指令),并设置一个待分析的位置,预分析从此位置逐字节分析,如果是前缀就设置分析状态(因为前缀可能改变默认地址尺寸和操作数的大小,影响后续指令长度),直到不是前缀,就认为是操作码,x86的op code长度一般为1字节,某些2字节,查表就可以直接找出指令长度了。
radare2 最近越来越流行,已经进入 github 前 25了,看到大佬们纷纷推荐,为了紧跟时代潮流,我也决定探究探究这款 神器 。下面画画重点,以便以后需要用了,可以方便查找。
https://github.com/radareorg/radare2