GNU 汇编器可能已经安装在您的系统上。尝试man as 以查看完整的使用信息。您可以使用as 编译单个文件并使用 ld 进行链接,如果您真的非常想要的话。
但是,GCC 是一个很棒的前端。它可以为您组装 .s 文件。例如:
$ cat >hello.s <<"EOF"
.section .rodata # read-only static data
.globl hello
hello:
.string "Hello, world!" # zero-terminated C string
.text
.global main
main:
push %rbp
mov %rsp, %rbp # create a stack frame
mov $hello, %edi # put the address of hello into RDI
call puts # as the first arg for puts
mov $0, %eax # return value = 0. Normally xor %eax,%eax
leave # tear down the stack frame
ret # pop the return address off the stack into RIP
EOF
$ gcc hello.s -no-pie -o hello
$ ./hello
Hello, world!
上面的代码是 x86-64。如果您想制作与位置无关的可执行文件 (PIE),则需要 lea hello(%rip), %rdi 和 call puts@plt。
非 PIE 可执行文件(位置相关)可以对静态数据使用 32 位绝对寻址,但 PIE 应该使用 RIP 相对 LEA。 (另见Difference between movq and movabsq in x86-64movq 和movabsq 都不是一个好的选择。)
如果您想编写 32 位代码,调用约定是不同的,并且 RIP 相对寻址不可用。 (所以你会在调用之前push $hello,然后弹出堆栈参数。)
如果您对某些东西的工作原理感到好奇,也可以将 C/C++ 代码直接编译为汇编:
$ cat >hello.c <<EOF
#include <stdio.h>
int main(void) {
printf("Hello, world!\n");
return 0;
}
EOF
$ gcc -S hello.c -o hello.s
另请参阅How to remove "noise" from GCC/clang assembly output?,了解有关查看编译器输出以及编写有用的小函数以编译为有趣的输出的更多信息。