【问题标题】:What assembly language does gcc produce on my system?gcc 在我的系统上生成什么汇编语言?
【发布时间】:2021-07-20 15:51:39
【问题描述】:

我正在尝试学习一些关于装配的知识。我决定首先查看从简单源代码生成的汇编文件。当然,我被指示轰炸,我不知道它们的含义,我开始在互联网上搜索它们的含义。在搜索时,我意识到我不知道我在寻找什么汇编语言..

有没有办法知道 gcc 生成哪种汇编语言?这个问题还有意义吗? 我主要对我的系统接受的程序集感兴趣(或者我应该这样说......)。使用 gcc 生成的代码见下文。

如果你意识到我有哪些知识空白,请链接相关文档阅读/学习。

系统:

操作系统:Windows 10 专业版

处理器:Intel(R) Core(TM) i5-5200U CPU @ 2.20GHz 2.20 GHz

类型:64 位操作系统,基于 x64 的处理器

//test.c

int main(){

    int x = 2;

    return 0;
}

 //test.s
.file   "test.c"
    .text
    .def    __main; .scl    2;  .type   32; .endef
    .globl  main
    .def    main;   .scl    2;  .type   32; .endef
    .seh_proc   main
main:
    pushq   %rbp
    .seh_pushreg    %rbp
    movq    %rsp, %rbp
    .seh_setframe   %rbp, 0
    subq    $48, %rsp
   .seh_stackalloc  48
   .seh_endprologue
    call    __main
    movl    $2, -4(%rbp)
    movl    $0, %eax
    addq    $48, %rsp
    popq    %rbp
    ret
   .seh_endproc
   .ident   "GCC: (Rev10, Built by MSYS2 project) 10.2.0"

【问题讨论】:

  • pushq、movl、ret,这些是指令,其余的是与语言相关的其他内容。该语言特定于工具(gnu 汇编器或 gcc)而不是目标(x86),因此完全涵盖这些指令如何工作的英特尔文档可能不会使用相同的语法(我不是在远程谈论 AT&T 与英特尔)。因此您可能需要查看 gnu 汇编器文档(binutils 的一部分)或从反汇编和机器代码与 intel 文档中推断。
  • 选择一个更好的指令集开始。

标签: c assembly x86-64 att instruction-set


【解决方案1】:

GCC 总是产生 GNU assembler 可以在任何平台上组装的 asm 输出。 (GAS / GNU as 是 GNU Binutils 的一部分,以及链接器 ld 等工具。)

在您的情况下,目标是 x86-64 Windows(可能来自 x86_64-w64-mingw32-gcc),
指令语法为AT&T syntax(GCC 和 GAS 默认适用于 x86,包括 x86-64)。

x86(包括 x86-64)的 GAS 中的注释字符为 #
任何以. 开头的都是指令;一些,如.globl main,将符号main导出为.o中可见的链接,一般对GAS是通用的;检查GAS manual

.seh_setframe %rbp, 0 这样的SEH 指令是Structured Exception Handling 的特定于Windows 的堆栈展开元数据,特定于Windows 对象文件格式。 (您可以 100% 忽略它,直到/除非您想了解回溯和异常处理如何在后台工作,而不依赖于传统帧指针链。AFAIK,它基本上等同于来自 @ 的 ELF/Linux .eh_frame 元数据987654348@ 指令。)

事实上你可以忽略几乎所有的指令,唯一真正重要的是像.text.data这样的部分,并且有些重要链接工作是.globl。这就是 https://godbolt.org/ 默认过滤指令的原因。


如果您需要 Intel 语法/助记符,您可以使用 gcc -masm=intel,您可以在 Intel 的手册中查找这些语法/助记符。 (https://software.intel.com/content/www/us/en/develop/articles/intel-sdm.html/https://www.felixcloutier.com/x86/)。另见How to remove "noise" from GCC/clang assembly output?。 (gcc -O1 -fverbose-asm 可能很有趣。)

如果您想学习 AT&T 语法,请参阅https://stackoverflow.com/tags/att/info。 GAS 手册也有一个关于 AT&T 与 Intel 语法的页面,但它不是作为教程编写的,即它假设您知道 x86 指令是如何工作的,并且正在寻找 GAS 用来描述它们的语法的详细信息:https://sourceware.org/binutils/docs/as/i386_002dVariations.html

(请记住,CPU 实际上运行机器代码,字节如何进入内存并不重要,只是它们确实如此。因此不同的汇编程序(如 NASM 与 GAS)和不同的语法(如 @987654354 @) 最终对机器在一条指令中可以做什么或不可以做什么有相同的限制。所有主流汇编程序都可以让您表达几乎每条指令可以做的所有事情,这只是了解立即数、寻址模式等的语法的问题on. Intel 和 AMD 的手册准确记录了 CPU 可以做什么,使用 Intel 语法,但没有详细说明语法或指令。)


资源(包括上面链接的一些):

【讨论】:

  • 大量资源也可以在x86 tag wiki 下方找到,主要感谢我们的常驻 x86 大师 @Peter Cordes :)
  • @Lundin:哦,是的,谢谢。我最近没有进行太多编辑以跟上新的规范。它有点臃肿,需要清理一下,但有很多好东西。
  • 这是 gnu 汇编器 (gas) 语法而不是 AT&T。语言特定于工具而不是目标,也不是目标在助记符中的位置......
  • @old_timer:指令使用 AT&T 语法,指令为 GAS 指令。我认为说它“不是 AT&T”对任何人都没有好处。您是否想指出我应该在关于它是 GAS 的段落中更多地讨论指令,而不是在关于它是 AT&T 语法的段落中,这是 GAS 对 x86 目标的默认设置?请注意,某些指令 是特定于目标的(针对目标文件格式),例如.seh_*
【解决方案2】:

有没有办法知道 gcc 生成的是哪种汇编语言?

是的,适合您的目标端口。这似乎是x86。这种汇编语言又具有各种风格和方言,具有大量历史:https://en.wikipedia.org/wiki/X86_assembly_language

当然,我会被那些我不知道它们是什么意思的指令轰炸

阅读 C 编译器生成的汇编器比阅读手工编码的汇编器困难得多。我建议从一些汇编教程开始,而不是使用人类编写的代码示例。

x86 也可能是其中最难的一种,因为它有各种口味,而且因为内核的复杂性。通常建议先学习一些简单的汇编程序来掌握它。

8 位微控制器是一个很好的起点。

【讨论】:

  • 如果您已经熟悉 C,那么作为简单编译器目标的干净机器可能是一个不错的起点,例如 RISC-V 或 ARM64。如果您使用正确的选项进行编译,并精心制作示例,编译器生成的 asm 可能是一种很好的学习方式。如果您不了解堆栈和调用约定的超级基础知识以及寄存器是什么,这不是一个好方法,所以可以从那开始,但是在那之后,任何时候您想知道“什么是好方法要在 asm 中做 X”,一个好的起点是用 C 编写一个函数并通过优化编译它。
  • 例如Matt Godbolt 的 CppCon2017 演讲“What Has My Compiler Done for Me Lately? Unbolting the Compiler's Lid”有一些编写 C 函数的好例子,这些函数不会优化,而是变成有趣的东西。另见How to remove "noise" from GCC/clang assembly output?
  • 如果您已经了解 C 并且想了解它的底层内容,我不推荐使用 8 位微。一旦您已经了解了用于制作简单编译器目标的机器的 asm(int 和指针都适合寄存器),那么您可以查看 8 位 micros 如何处理指针(例如 AVR reg 对或 如果指针大多只支持 8 位偏移,则不处理指针)。此外,如果您没有堆栈,那么“局部变量”的工作方式将与您习惯于思考 C 的方式不同。
  • @PeterCordes 学校仍然喜欢使用古老的摩托罗拉 68k 来教授汇编程序。即使在我 20 年前上大学的时候,它也已经很老了 :) 就我个人而言,我发现基于摩托罗拉的汇编程序更容易阅读,但这可能只是个人喜好。 HC08、AVR、STM8、R8C 等 8 位 micros 都使用了它的一些风格,这些系列仍然主要在生产中。
  • m68k 是我学习的第一个组件,是的,它被广泛认为是一个非常干净的 CISC 设计,没有很多奇怪的东西,非常适合学习。 (我在大学一年级学习 C 的时候,家里有我父亲的 Atari Mega4 STe 台式机(16MHz 68000),带有 GCC 和我父亲安装的类似 unix 的 shell。我找到了一个定点 Mandelbrot 程序在杂志或书籍中并输入它,当我厌倦了缓慢的编译时间并开始编辑 asm 时正在优化它。我父亲有一些 m68k asm 书籍,但这些天互联网会很好。)跨度>
猜你喜欢
  • 2010-11-18
  • 1970-01-01
  • 1970-01-01
  • 2011-04-05
  • 2022-01-02
  • 1970-01-01
  • 2022-12-09
  • 1970-01-01
  • 2021-10-28
相关资源
最近更新 更多