在我的Mac上查看一些x86_64的汇编代码,我看到以下说明:
48 c7 c0 01 00 00 00 movq $0x1,%rax
但是我找不到分解操作码的参考。似乎 48c7 是一个移动指令,c0 定义了 %rax 寄存器,等等。
那么,我在哪里可以找到告诉我所有这些的参考资料?
我知道 http://ref.x86asm.net/,但查看 48 个操作码,我没有看到任何类似于移动的东西。
实际上,mov
0xc7在那里;在这种情况下,0x48是一个长模式REX。W 前缀。
还回答评论中的问题:0xc0是b11000000。在这里,您可以发现,对于REX.B = 0
(因为 REX 前缀是 0x48,.B 位未设置),0xc0表示"RAX 是第一个操作数"(在英特尔语法中; mov rax, 1
,RAX是第一个,或者在mov
的情况下,输出操作数)。你可以在这里找到如何阅读ModR/M。
当你查看二进制时
48 c7 c0 01 00 00 00
您需要拆卸它才能理解它的含义。
反汇编的算法并不困难,但很复杂。 它假设查找多个表。
该算法在英特尔开发人员手册的第二卷中进行了描述,
Intel® 64 and IA-32 Architectures
Software Developer’s Manual
Volume 2 (2A, 2B & 2C):
Instruction Set Reference, A-Z
您从名为 INSTRUCTION FORMAT
的章节开始阅读。
或者,有一些好书专门用了一整章来讨论这个主题,例如
X86 Instruction Set Architecture, Mindshare, by Tom Shanley.
整整一章专门讨论拆解二进制 X86。
或者,您可以从AMD制作的相同语言的手册中开始阅读通用算法:
AMD64 Architecture
Programmer’s Manual
Volume 3:
General-Purpose and System Instructions
在这里,在第Instruction Encoding
章中,您将找到定义这种指令语言的自动机,并且从此图形方案中,您可以轻松编写解码器。
完成此操作后,您可以返回英特尔手册第 2 卷,并将其用作参考书。
我还发现 http://opensecuritytraining.info/的逆向工程课程很有用。 这个网站是由CMU的博士生创建的,其中大部分都做得不好,但需要更长的时间来研究和应用它。
了解基本思想后,您可以查看实现该算法的免费项目。 我发现distorm项目很有用。 一开始,重要的是不要看抽象项目(如qemu或objdump),它们试图在相同的代码中实现多种语言的dissasemblers,否则你会迷路。 Distorm
只关注 x86,并正确、详尽地实现它。 它用正式语言传达了X86语言的定义,而英特尔和AMD手册则使用自然语言来定义X86语言。
另一个运行良好的项目是 udis86 .