You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

关于x86_64架构下AT&T格式汇编Hello World程序的编译与正确性疑问

关于x86_64架构下AT&T格式汇编Hello World程序的编译与正确性疑问

嘿,很高兴看到你在手动编写调用系统调用的汇编程序,这可是深入理解Linux底层运作的好方式!咱们逐个解决你的疑问:

1. .s.S 后缀的区别,以及编译方式的正确性

首先得明确这两个后缀的规范含义:

  • 小写的 .s:代表已经完成预处理的汇编源文件,文件里不包含任何C预处理器指令(比如#define#include这类),可以直接用as汇编成目标文件。
  • 大写的 .S:代表需要经过预处理的汇编源文件,文件里可以包含C预处理器支持的语法,比如宏定义、头文件引用。这类文件不能直接用as编译——如果你强行用as hello.S -o hello.o,预处理器指令会被当成无效的汇编语法报错。正确的做法是用gcc -c hello.S -o hello.o,gcc会自动先调用cpp(C预处理器)处理文件,再调用as汇编。

回到你的情况:你的代码里没有任何预处理器指令,所以即使把文件命名为.S,直接用as编译也能正常工作(因为没有需要预处理的内容),但从命名规范来说,用.s更准确,能清晰告诉别人这个汇编文件不需要预处理。

2. 为什么 gcc -S demo.i 生成 demo.s 而不是 demo.S

demo.i是已经完成预处理的C源文件——它已经展开了所有宏、头文件,没有任何需要再处理的预处理器指令了。gcc把它编译成汇编代码时,生成的是不需要再预处理的汇编文件,所以按照规范用.s后缀,符合“已预处理汇编文件”的定义。

3. 你的Hello World汇编代码是否100%正确?

从功能和正确性来说,你的代码完全没问题:

  • 你正确使用了x86_64 Linux的系统调用约定:rax存系统调用号(1对应write60对应exit),参数依次存在rdirsirdx里。
  • lea msg(%rip), %rsi是正确的位置无关代码(PIC)写法,符合现代Linux默认的PIC可执行文件要求,能确保程序在不同内存地址都能正常运行。
  • .set msglen, (. - msg)的方式计算字符串长度非常准确,因为.rodata段是连续存储的,当前位置减去msg的地址就是字符串的字节数。

不过有个小细节可以提一下:在x86_64的System V ABI中,main函数的返回值是通过rax寄存器返回给调用者(也就是C运行时),你的代码直接调用exit系统调用退出,这完全没问题——很多纯汇编写的程序都会这么做,毕竟exit系统调用是直接终止进程,跳过了C运行时的收尾步骤,对于简单程序来说完全够用。

总结:你的代码功能完全正确,写法也符合x86_64 Linux的规范,放心用就好!

备注:内容来源于stack exchange,提问作者Kode1000

火山引擎 最新活动