c - gcc 在我的系统上生成什么汇编语言?

标签 c assembly x86-64 att instruction-set

我正在尝试学习一些关于组装的知识。我决定从简单的源代码中查看生成的程序集文件开始。当然,我被指令轰炸,我不知道它们的意思,我开始在互联网上搜索它们的含义。在搜索时,我意识到我不知道我在寻找什么汇编语言..
有没有办法知道 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"

最佳答案

GCC 始终生成 GNU assembler 可以在任何平台上组装的 asm 输出。 (GAS/GNU as 是 GNU Binutils 的一部分,以及 ld 等工具,一个链接器。)
在您的情况下,目标是 x86-64 Windows (来自 x86_64-w64-mingw32-gcc 的概率),
指令语法为 AT&T syntax (x86 包括 x86-64 的 GCC 和 GAS 默认值)。
在 GAS for x86(包括 x86-64)中,注释字符为 #
任何以 . 开头的都是 指令 ;一些,例如 .globl main 导出符号 main 为链接的 .o 中可见的符号,通常对 GAS 通用;检查 GAS manual
.seh_setframe %rbp, 0 这样的 SEH 指令是 Structured Exception Handling 的特定于 Windows 的堆栈展开元数据,特定于 Windows 对象文件格式。 (您可以 100% 忽略,直到/除非您想了解回溯和异常处理如何在幕后工作,而不依赖于传统帧指针链。AFAIK,它基本上等同于来自 .eh_frame 指令的 ELF/Linux .cfi 元数据。 )
事实上,你可以忽略几乎所有的指令 ,唯一真正重要的部分是像 .text.data 这样的部分,并且对于使链接工作有些重要的是 .globl 。这就是默认情况下 https://godbolt.org/ 过滤指令的原因。

如果您想要英特尔语法/助记符,您可以使用 gcc -masm=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)和不同的语法(如 .intel_syntax noprefix)最终具有机器在一条指令中可以做什么或不能做什么的限制相同。所有主流汇编程序都可以让您表达每条指令可以做的几乎所有事情,只需了解立即数、寻址模式等的语法。英特尔和 AMD 的手册准确地记录了 CPU 可以做什么,使用 Intel 语法,但没有确定语法或指令的细节。)

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

  • Matt Godbolt 的 CppCon2017 演讲“What Has My Compiler Done for Me Lately? Unbolting the Compiler's LidHow to remove "noise" from GCC/clang assembly output?
  • x86 tag wiki
  • https://stackoverflow.com/tags/att/info
  • https://sourceware.org/binutils/docs/as/ GAS 手册
  • https://software.intel.com/content/www/us/en/develop/articles/intel-sdm.html 英特尔手册
  • https://support.amd.com/TechDocs/24594.pdf(AMD vol.3 手册:通用说明)
  • 关于c - gcc 在我的系统上生成什么汇编语言?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67280763/

    相关文章:

    c - 从 C 源代码中自动删除未使用的局部变量

    assembly - 如果函数没有显式使用 'ret',为什么没有返回值

    linux - 使用 mmap 函数创建数组。汇编器 x86_64 AT&T

    linux - printf 上的段错误 - NASM 64 位 Linux

    c++ - 仅在按下键时调用函数,而不是在释放键时调用函数

    c - 文件格式无法识别;视为链接器脚本 - 为 arm 处理器编译 c 代码

    c - 修改 c 中的代码行以不包含无符号变量或强制转换。 (?)

    delphi - 如何在 asm block 中引发异常?

    assembly - 如何将数字类型位置转换为x,y类型位置?

    x86 - 使用Intel AVX从压缩 double 向量存储单个 double