在 Linux 源代码中,以 .S 为扩展名的文件是“纯”汇编语言的文件。这里,我们结合具体的例子再介绍一些 AT&T 汇编语言的相关知识。
1 . GNU 汇编程序 GAS ( GNU Assembly 和连接程序
当你编写了一个程序后,就需要对其进行汇编( assembly )和连接。在 Linux 下有两种方式,一种是使用汇编程序 GAS 和连接程序 ld ,一种是使用 gcc 。我们先来看一下 GAS 和 ld:
GAS 把汇编语言源文件( .o )转换为目标文件( .o ),其基本语法如下:
as filename.s -o filename.o
一旦创建了一个目标文件,就需要把它连接并执行,连接一个目标文件的基本语法为:
ld filename.o -o filename
这里 filename.o 是目标文件名,而 filename 是输出 ( 可执行 ) 文件。
GAS 使用的是 AT&T 的语法而不是 Intel 的语法,这就再次说明了 AT&T 语法是 Unix 世界的标准,你必须熟悉它。
如果要使用 GNC 的 C 编译器 gcc ,就可以一步完成汇编和连接,例如:
gcc -o example example.S
这里, example.S 是你的汇编程序,输出文件(可执行文件)名为 example 。其中,扩展名必须为大写的 S ,这是因为,大写的 S 可以使 gcc 自动识别汇编程序中的 C 预处理命令,像 #include 、 #define 、 #ifdef 、 #endif 等,也就是说,使用 gcc 进行编译,你可以在汇编程序中使用 C 的预处理命令。
2. AT&T 中的节( Section )
在 AT&T 的语法中,一个节由 .section 关键词来标识,当你编写汇编语言程序时,至少需要有以下三种节:
.section .data : 这种节包含程序已初始化的数据,也就是说,包含具有初值的那些变量,例如:
hello : .string "Hello world!\n"
hello_len : .long 13
.section .bss :这个节包含程序还未初始化的数据,也就是说,包含没有初值的那些变量。当操作
系统装入这个程序时将把这些变量都置为 0 ,例如:
name : .fill 30 # 用来请求用户输入名字
name_len : .long 0 # 名字的长度 ( 尚未定义 )
当这个程序被装入时, name 和 name_len 都被置为 0 。如果你在 .bss 节不小心给一个变量赋了初值,这个值也会丢失,并且变量的值仍为 0 。
使用 .bss 比使用 .data 的优势在于, .bss 节不占用磁盘的空间。在磁盘上,一个长整数就足以存放 .bss 节。当程序被装入到内存时,操作系统也只分配给这个节 4 个字节的内存大小。
注意:编译程序把 .data 和 .bss 在 4 字节上对齐( align ),例如, .data 总共有 34 字节,那么编译程序把它对其在 36 字节上,也就是说,实际给它 36 字节的空间。
.section .text :这个节包含程序的代码,它是只读节,而 .data 和 .bss 是读/写节。