我正在尝试学习X86汇编(用于学习逆向工程)。 我学习了C#和C \ C ++语言以及IL
可能我的主要问题是英语,因为我是波斯语,而且我也找不到任何有用的文件来学习用波斯语写的X86程序集。所以我决定做我为学习C#和C ++所做的事情。 我试过阅读X86样本和你好世界,但我失败了,因为我无法理解我必须选择哪个注册表以及仅通过查看源代码无法解决的其他问题。
所以我决定改变策略并做一个挑战:写一个X86反汇编程序 我很生气,我知道。但我们不能说这是不可能的。 第一个认为我需要理解(但没有记住)的是这些表:http://ref.x86asm.net/coder32.html
我对操作码很好,但是我无法理解如何计算操作数的大小或寄存器的十六进制字节呢?
抱歉我的英语不好。
PS。我想用C#
来做答案 0 :(得分:6)
所以,既然这个话题似乎让你感兴趣,那么让我给你一个概述。 x86指令最多包含五个部分,最长为15个字节:
prefixes opcode operand displacement immediate
可以生成长度超过15个字节的编码,但CPU会拒绝它们。除操作码之外的所有五个部分都是可选的。您可以按如下方式找到它们的长度:
f0
锁定,f2
重新,f3
重复,2e
cs ,36
ss ,3e
ds ,26
es ,64
fs ,65
gs ,66
操作数大小覆盖以及67
地址大小覆盖。但是,只有f0
,f2
,f3
中只有一个26
,2e
,36
,3e
, 64
,65
一次被识别。如果提供了来自每个组的多个前缀,则CPU的行为会有所不同。 VEX和EVEX编码指令可能只有段覆盖和地址大小覆盖传统前缀,因为其他前缀包含在VEX和EVEX前缀下。40
到4f
之一。在其他模式中,这些字节是指令,而不是前缀,您的解码器必须考虑到这一点。与传统前缀一样,VEX或EVEX编码指令不能具有REX前缀。c4
和c5
可以引入用于编码某些现代指令的 VEX前缀。在长模式下,它们总是这样做,但在其他模式下,你必须在之后检查字节:将其解释为modr / m字节,如果它编码r,r
操作数对,它是一个VEX前缀,否则为les
或lds
的操作码。以c4
开头的VEX前缀长度为两个字节,c5
为三个字节。 VEX前缀还编码0f
,0f 38
和0f 3a
操作码前缀,这些前缀在VEX编码指令中被省略。请注意,通常,使用VEX前缀不是可选的。例如,pdep
编码为VEX.NDS.LZ.F2.0F38.W0 F5 /r
(例如c4 e2 7b f5 c0
为pdep eax,eax,eax
),但相应的遗留指令f2 0f 38 f5 r/m32
(例如f2 0f 38 f5 c0
代表pdep eax,eax
1}})无效。请注意,相同的操作码可以与VEX前缀一起存在而且没有,这两者可能意味着不同的东西。例如,0f 77
为emms
,但VEX.128.0F.WIG 77
(即c5 f8 77
)为vzeroupper
。62
引入了 EVEX前缀,用于编码AVX512指令。与VEX前缀类似,需要检查接下来的几个字节,以区分EVEX前缀和bound
指令。 EVEX前缀总是四个字节长,并且像VEX前缀一样编码操作码的一部分。在前缀之后,操作码如下。最初,操作码始终是单个字节,但随后它们用完了空间,所以现在它是单个字节或以0f
,0f 38
或{{1为前缀的单个字节}}。如果指令是VEX编码,则不存在这些前缀。请注意,某些前缀可能会更改编码的指令。例如,操作码0f 3a
为0f b8
(输入IA-64模式),但jmpe
不是f3 0f b8
,而是repe jmpe
。
操作码和前缀决定编码哪条指令。从现在开始,它几乎一帆风顺。根据指令,可能会跟随 modr / m 字节。根据modr / m字节和地址覆盖前缀,可以跟随 sib字节和一个,两个或四个位移字节。最后,根据指令,操作数大小覆盖前缀和REX前缀,可以跟随一个,两个,四个,六个或八个立即字节。
这与我在Stack Overflow答案范围内给出的描述一样多。所以 TL; DR:这真的很复杂。