X86汇编 - 如何计算指令操作码长度(以字节为单位)

时间:2017-08-21 16:02:07

标签: c# assembly

我正在尝试学习X86汇编(用于学习逆向工程)。 我学习了C#和C \ C ++语言以及IL

可能我的主要问题是英语,因为我是波斯语,而且我也找不到任何有用的文件来学习用波斯语写的X86程序集。所以我决定做我为学习C#和C ++所做的事情。 我试过阅读X86样本和你好世界,但我失败了,因为我无法理解我必须选择哪个注册表以及仅通过查看源代码无法解决的其他问题。

所以我决定改变策略并做一个挑战:写一个X86反汇编程序 我很生气,我知道。但我们不能说这是不可能的。 第一个认为我需要理解(但没有记住)的是这些表:http://ref.x86asm.net/coder32.html

我对操作码很好,但是我无法理解如何计算操作数的大小或寄存器的十六进制字节呢?

抱歉我的英语不好。

PS。我想用C#

来做

1 个答案:

答案 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地址大小覆盖。但是,只有f0f2f3中只有一个262e363e6465一次被识别。如果提供了来自每个组的多个前缀,则CPU的行为会有所不同。 VEX和EVEX编码指令可能只有段覆盖和地址大小覆盖传统前缀,因为其他前缀包含在VEX和EVEX前缀下。
  • 在长模式下(仅在那里),指令可以在所有传统前缀之后立即具有 REX前缀。 REX前缀是404f之一。在其他模式中,这些字节是指令,而不是前缀,您的解码器必须考虑到这一点。与传统前缀一样,VEX或EVEX编码指令不能具有REX前缀。
  • 字节c4c5可以引入用于编码某些现代指令的 VEX前缀。在长模式下,它们总是这样做,但在其他模式下,你必须在之后检查字节:将其解释为modr / m字节,如果它编码r,r操作数对,它是一个VEX前缀,否则为leslds的操作码。以c4开头的VEX前缀长度为两个字节,c5为三个字节。 VEX前缀还编码0f0f 380f 3a操作码前缀,这些前缀在VEX编码指令中被省略。请注意,通常,使用VEX前缀不是可选的。例如,pdep编码为VEX.NDS.LZ.F2.0F38.W0 F5 /r(例如c4 e2 7b f5 c0pdep eax,eax,eax),但相应的遗留指令f2 0f 38 f5 r/m32(例如f2 0f 38 f5 c0代表pdep eax,eax 1}})无效。请注意,相同的操作码可以与VEX前缀一起存在而且没有,这两者可能意味着不同的东西。例如,0f 77emms,但VEX.128.0F.WIG 77(即c5 f8 77)为vzeroupper
  • 字节62引入了 EVEX前缀,用于编码AVX512指令。与VEX前缀类似,需要检查接下来的几个字节,以区分EVEX前缀和bound指令。 EVEX前缀总是四个字节长,并且像VEX前缀一样编码操作码的一部分。

在前缀之后,操作码如下。最初,操作码始终是单个字节,但随后它们用完了空间,所以现在它是单个字节或以0f0f 38或{{1为前缀的单个字节}}。如果指令是VEX编码,则不存在这些前缀。请注意,某些前缀可能会更改编码的指令。例如,操作码0f 3a0f b8(输入IA-64模式),但jmpe不是f3 0f b8,而是repe jmpe

操作码和前缀决定编码哪条指令。从现在开始,它几乎一帆风顺。根据指令,可能会跟随 modr / m 字节。根据modr / m字节和地址覆盖前缀,可以跟随 sib字节和一个,两个或四个位移字节。最后,根据指令,操作数大小覆盖前缀和REX前缀,可以跟随一个,两个,四个,六个或八个立即字节

这与我在Stack Overflow答案范围内给出的描述一样多。所以 TL; DR:这真的很复杂。