GCC允许在C程序中嵌入汇编代码,或者直接编写一个纯汇编文件并使用GCC进行编译和链接。
下面是一个使用AT&T语法的简单汇编程序示例,该程序在Linux系统上打印"Hello, World!"。这个程序是为x86架构编写的,并且假设正在使用32位系统或已经安装了必要的多架构支持。
首先,创建一个名为hello.s
的汇编源文件:
# hello.s
.section .data
hello_string:
.string "Hello, World!\n"
.section .text
.global _start
_start:
# 写入系统调用
movl $4, %eax # 系统调用号 (sys_write)
movl $1, %ebx # 文件描述符 (stdout)
movl $hello_string, %ecx # 字符串地址
movl $14, %edx # 字符串长度(包括换行符)
int $0x80 # 调用内核
# 退出系统调用
movl $1, %eax # 系统调用号 (sys_exit)
xorl %ebx, %ebx # 退出状态码
int $0x80 # 调用内核
然后,使用GCC编译并链接这个程序:
gcc -static -o hello hello.s -nostartfiles -nostdlib
这里的编译选项解释如下:
-
-static
:生成静态链接的可执行文件,这样就不需要动态链接器来加载运行时库。 -
-nostartfiles
:不链接标准启动文件,这些文件通常包含程序入口点(如_start
),因为我们已经在汇编代码中提供了。 -
-nostdlib
:不链接标准C库,这样GCC就不会自动包含例如libc
这样的库。
编译成功后,就可以运行生成的可执行文件了:
./hello
如果一切正常,它应该在终端上打印出"Hello, World!"。
这个程序没有使用C标准库或任何其他的库函数。它直接通过Linux的系统调用来输出字符串和结束程序。此外,这个程序是针对32位系统的;如果正在使用64位系统,需要对代码进行一些修改,包括使用不同的寄存器和系统调用号。在64位系统上,可能还需要使用-m32
选项来告诉GCC生成32位代码(并且确保已经安装了必要的32位开发工具和库)。