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

moi*_*ien 0 c# assembly

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

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

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

我对操作码很好,但我不明白如何计算操作数的大小或者寄存器十六进制字节呢?

对不起,我的英语不好.

PS.我想用C#做它

fuz*_*fuz 6

所以,既然这个话题似乎让你感兴趣,那么让我给你一个概述.x86指令最多包含五个部分,最长为15个字节:

prefixes opcode operand displacement immediate
Run Code Online (Sandbox Code Playgroud)

可以生成长度超过15个字节的编码,但CPU拒绝它们.除操作码之外的所有五个部分都是可选的.你可以找到他们的长度如下:

  • 指令可以包含任意数量的传统前缀.它们是:f0 lock,f2 repne,f3 repe,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前缀下.
  • 在长模式(仅在那里),指令可以在所有传统前缀之后立即具有REX前缀.REX前缀是40to之一4f.在其他模式中,这些字节是指令,而不是前缀,您的解码器必须考虑到这一点.与传统前缀一样,VEX或EVEX编码指令不能具有REX前缀.
  • 字节c4并且c5可以引入用于编码一些现代指令的VEX前缀.在长模式下,它们总是这样做,但在其他模式下,您必须事后检查字节:将其解释为modr/m字节,如果它对r,r操作数对进行编码,则它是VEX前缀,否则为les或者为操作码lds.开头的VEX前缀c4是两个字节长,有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)是无效的.请注意,相同的操作码可以与VEX前缀一起存在而且没有,这两者可能意味着不同的东西.例如,0f 77是(emms但)是.VEX.128.0F.WIG 77c5 f8 77vzeroupper
  • 该字节62引入了EVEX前缀,用于编码AVX512指令.与VEX前缀类似,需要检查接下来的几个字节,以区分EVEX前缀和bound指令.EVEX前缀总是四个字节长,并且像VEX前缀一样编码操作码的一部分.

在前缀之后,操作码如下.最初,操作码总是一个单字节,但接着就跑出空位,所以现在要么单字节或前缀一个字节0f,0f 380f 3a.如果指令是VEX编码,则不存在这些前缀.请注意,某些前缀可能会更改编码的指令.例如,操作码0f b8jmpe(回车IA-64模式),但f3 0f b8repe jmpe而是popcnt.

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

这与我在Stack Overflow答案范围内给出的描述差不多.所以TL; DR:它真的很复杂.