我正在努力学习一些关于汇编的知识。我决定从查看从简单源代码生成的程序集文件开始。当然,我被指令轰炸,我不知道它们的意思,我开始在互联网上寻找它们的含义。在搜索过程中,我意识到我不知道自己在寻找什么汇编语言。。
有没有办法知道gcc生成哪种汇编语言?这个问题有道理吗?我主要感兴趣的是我的系统接受的程序集(或者我应该说…)。请参阅下面使用gcc生成的代码。
如果你意识到我有哪些知识空白,请链接相关文件阅读/学习。
系统:
操作系统:Windows 10 Pro
处理器:英特尔(R)酷睿(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总是生成asm输出,GNU汇编程序可以在任何平台上汇编这些输出。(GAS/GNUas
是GNU Binutils的一部分,还有ld
等链接器工具。)
在您的情况下,目标是x86-64 Windows(问题来自x86_64-w64-mingw32-gcc),
和指令语法为AT&T语法(x86(包括x86-64)的GCC和GAS默认值)。
对于x86(包括x86-64),注释字符是GAS中的#
任何以.
开头的指令都是指令;一些,如.globl main
,将符号main
导出为在.o
中可见以进行链接,通常对GAS是通用的;查看GAS手册。
像.seh_setframe %rbp, 0
这样的SEH指令是用于结构化异常处理的特定于Windows的堆栈展开元数据,特定于Windows对象文件格式。(你可以100%忽略它,直到/除非你想了解回溯和异常处理是如何在后台工作的,而不依赖于遗留帧指针链。AFAIK,它基本上相当于.cfi
指令中的ELF/Linux.eh_frame
元数据。)
事实上,您可以忽略几乎所有的指令,只有真正重要的指令是.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";噪声";来自GCC/clang程序集输出?。(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能做什么,使用英特尔语法,但没有明确语法或指令的细节。)
资源(包括上面链接的一些):
- Matt Godbolt的CppCon2017演讲"我的编译器最近为我做了什么?解开编译器的盖子">以及如何删除";噪声";从GCC/clang汇编输出
- x86标记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手册第3卷:通用说明)
有办法知道gcc生成哪种汇编语言吗?
是的,就是你的目标端口。它看起来是x86。这种汇编语言又有各种风格和方言,有着丰富的历史:https://en.wikipedia.org/wiki/X86_assembly_language
当然,我会被指令轰炸,我不知道它们是什么意思
阅读C编译器生成的汇编程序比阅读手工编码的汇编程序困难得多。我建议从一些汇编教程开始,使用人工编写的代码示例。
x86可能也是其中最难的一个,因为它有各种各样的风格,也因为内核的复杂性。通常建议先学习一些简单的汇编程序,以掌握它的窍门
8位微控制器是一个很好的起点。