学习阅读GCC汇编输出

47

我正在考虑学习一些汇编语言的基础知识。我的当前目标很简单:了解GCC编译C/C++时使用-S开关生成x86/x86-64汇编代码的基本概念

我只需要掌握足够的技能,例如查看单个函数并验证GCC是否优化掉了我预期会消失的内容等简单操作。

有没有人有/知道一个真正简明扼要的汇编介绍,与GCC相关,并专门用于阅读目的,列出任何准备阅读汇编的人都应该掌握的最重要的指令清单?


你还没有说明你感兴趣的目标汇编语言是什么。Intel x86?PowerPC? - Brian Neal
6个回答

31

您应该使用GCC的-fverbose-asm选项。它会使编译器输出附加信息(以注释形式),从而更容易理解汇编代码与原始C/C++代码之间的关系。


26
如果您使用gcc或clang,-masm=intel参数会告诉编译器生成Intel语法的汇编代码而不是AT&T语法,并且--save-temps参数会告诉编译器在调用GCC的目录中保存临时文件(预处理源代码、汇编输出、未链接的目标文件)。
通过所有可获得的资源,轻松了解x86汇编应该很容易。这里有一个这样的资源:http://www.cs.virginia.edu/~evans/cs216/guides/x86.html
您还可以使用disasm和gdb来查看编译程序正在执行的操作。

4
如果您使用GDB反汇编,您也可以使用“set disassembly-flavor intel”来使用Intel语法。 - Travis Gockel

4

遇到新设备时,我通常会查找处理器文档,并在遇到未知的操作码时进行查询。

在英特尔处理器上,操作码相对来说比较合理。而在我的看法中,PowerPC 的操作码则不太好理解。MIPS 是我最喜欢的处理器之一。对于 MIPS 处理器,我借了我的邻居的参考书,针对 PPC 处理器,我有一本 IBM 文档的 PDF 文件很方便查询。(对于英特尔处理器,我基本上是猜测然后观察寄存器以确保我的猜测是否正确!嘿嘿)

基本上,汇编本身并不难。它主要有三个功能:在内存和寄存器之间传递数据、在寄存器中操作数据以及更改程序计数器。将您所选择的语言与汇编语言进行映射需要一些学习(例如,学习如何识别虚拟函数调用),此时,“集成”的源代码和反汇编视图(例如在 Visual Studio 中可以获得的)非常有用。


x86... 合理吗?这是一个新的东西。 - jalf

1

与高级语言不同的是,能够阅读汇编语言和能够编写汇编语言之间几乎没有什么(如果有的话)区别。指令与 CPU 操作码之间存在一对一的关系 - 在保留对代码行所做操作的理解的同时,没有需要跳过的复杂性。(这不像高级语言中可以看到一个说“print $var”的行而不需要知道或关心它如何输出到屏幕。)

如果您仍然想学习汇编语言,请尝试 Jeff Duntemann 的书 Assembly Language Step-by-Step: Programming with Linux


1
我不同意(但不会因为这个原因而投反对票);理解已知为良好形式的东西并自己创建良好形式的代码要容易得多。能够阅读汇编语言当然有助于/编辑/汇编语言,但仅仅能够阅读远远不能从头开始创作甚至是微不足道的功能。我可能能够在我学过的外语中听懂别人和我说话,但我肯定无法以良好的形式讲出它们! - dash-tom-bang

0
我相信有很多入门书籍和网站,但实际上学习的一种相当有效的方法是获取英特尔的参考资料,然后尝试在您喜欢的高级语言中进行简单的操作(如整数运算和布尔逻辑),然后查看生成的二进制代码。

由于GCC使用AT&T语法进行输出,这使得情况有些复杂。MOV不仅仅被称为MOV,而且操作数的顺序并不总是按照英特尔手册中列出的顺序。 - Michael Madsen
2
如果您正在编译x86架构的程序,可以使用编译器标志-masm=intel,让gcc输出更类似于英特尔手册的汇编代码。 - nategoose

0

“随便看汇编代码”哈哈(友好地)

我会从在运行时使用gdb开始;这样你可以更好地感受到正在发生的事情。然后也许这只是我的想法。它将为您反汇编一个函数(disass func),然后您可以逐步执行它。

如果您这样做仅仅是为了检查优化 - 不用担心。

a)编译器做得很好

b)无论如何,您都无法理解它在做什么(没有人能够理解)


7
有时候我觉得优化过的代码更易读,因为它能够发现重复的部分并将其改为类似于我写的样式。 - avpx
5
对于我自己而言,我知道仅出于检查优化是个好主意。原因是每次我看到编译器实际上在情况X方面做了聪明的事情时,我将来就不会浪费时间想知道。avpx也有非常好的观点。 - porgarmingduod
1
+1,这是个好主意,我已经在gdb的CW上添加了disass func:http://stackoverflow.com/questions/2588853/the-community-driven-gdb-primer/2611474#2611474。请随意编辑我所写的内容。 - user257111
参见如何从GCC / clang汇编输出中去除“噪音”? - Matt Godbolt在CppCon2017上做了一个演讲,题为“我的编译器最近对我做了什么?解开编译器的盖子”,他展示的编译器汇编输出都是在启用优化的情况下生成的。(否则答案将是“什么也没有”。) - Peter Cordes
CPU保留了以程序顺序一条指令一次地运行代码的“幻觉”(除了来自其他核心的内存影响)。因此,就理解代码的功能和正确性而言,没有问题。 - Peter Cordes
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接