GCC 中的内嵌汇编语言
一.声明
虽然 Linux 的核心代码大部分是用 C 语言编写的,但是不可避免的其中还是有一部分是用汇编语言
写成的。有些汇编语言代码是直接写在汇编源程序中的,特别是 Linux 的启动代码部分;还有一些则是利
用 gcc 的内嵌汇编语言嵌在 C 语言程序中的。这篇文章简单介绍了 gcc 中的内嵌式汇编语言,主要想帮助
那些才开始阅读 Linux 核心代码的朋友们能够更快的入手。
写这篇文章的主要信息来源是 GNU 的两个 info 文件:as.info 和 gcc.info,如果你觉得这篇文章中的介
绍还不够详细的话,你可以查阅这两个文件。当然,直接查阅这两个文件可以获得更加权威的信息。如果
你不想被这两篇文档中的一大堆信息搞迷糊的话,我建议你先阅读一下这篇文章,然后在必要时再去查阅
更权威的信息。
二.简介
在 Linux 的核心代码中,还是存在相当一部分的汇编语言代码。如果你想顺利阅读 Linux 代码的话,
你不可能绕过这一部分代码。在 Linux 使用的汇编语言代码中,主要有两种格式:一种是直接写成汇编语
言源程序的形式,这一部分主要是一些 Linux 的启动代码;另一部分则是利用 gcc 的内嵌式汇编语言语句
asm 嵌在 Linux 的 C 语言代码中的。这篇文章主要是介绍第二种形式的汇编语言代码。
首先,我介绍一下 as 支持的汇编语言的语法格式。大家知道,我们现在学习的汇编语言的格式主要
是 Intel 风格的,而在 Linux 的核心代码中使用的则是 AT&T 格式的汇编语言代码,应该说大部分人对这
种格式的汇编语言还不是很了解,所以我觉得有必要介绍一下。
接着,我主要介绍一下 gcc 的内嵌式汇编语言的格式。gcc 的内嵌式汇编语言提供了一种在 C 语言源
程序中直接嵌入汇编指令的很好的办法,既能够直接控制所形成的指令序列,又有着与 C 语言的良好接口,
所以在 Linux 代码中很多地方都使用了这一语句。
三.gcc 的内嵌汇编语言语句 asm
利用 gcc 的 asm 语句,你可以在 C 语言代码中直接嵌入汇编语言指令,同时还可以使用 C 语言的表
达式指定汇编指令所用到的操作数。这一特性提供了很大的方便。
要使用这一特性,首先要写一个汇编指令的模板(这种模板有点类似于机器描述文件中的指令模
板),然后要为每一个操作数指定一个限定字符串。例如:
extern __inline__ void change_bit(int nr,volatile void *addr)
{
__asm__ __volatile__( LOCK_PREFIX
"btcl %1,%0"
:"=m" (ADDR)
:"ir" (nr));
}
上面的函数中:
LOCK_PREFIX:这是一个宏,如果定义了__SMP__,扩展为"lock;",用于指定总线锁定前缀,否
则扩展为""。
ADDR:这也是一个宏,定义为(*(volatile struct __dummy *) addr)
"btcl %1,%0":这就是嵌入的汇编语言指令,btcl 为指令操作码,%1,%0 是这条指令两个操作数
的占位符。后面的两个限定字符串就用于描述这两个操作数。
: "=m" (ADDR):第一个冒号后的限定字符串用于描述指令中的“输出”操作数。刮号中的 ADDR 将
操作数与 C 语言的变量联系起来。这个限定字符串表示指令中的“%0”就是 addr 指针指向的内存操作数。