缘起
在 Linux-0.11 中遇到了这种用法,所以想做个实验以加深理解。
实验代码
分为2个源文件和1个Makefile.
a.s
.globl phone_num
.data
phone_num:
.word 0x1234
.word 0x5678
可以认为,phone_num是一个全局变量,可以供其他文件链接,phone_num的值是0x56781234.
b.c
#include <stdio.h>
extern unsigned int phone_num; //声明a.s中的phone_num变量
int main(void)
{
printf("phone = 0x%x\n", phone_num);
printf("&phone_num = %p\n", &phone_num);
return 0;
}
Makefile
TGT =main
C_SRC = $(wildcard *.c)
ASM_SRC = $(wildcard *.s)
OBJ =$(patsubst %.c,%.o,$(C_SRC))
OBJ +=$(patsubst %.s,%.o,$(ASM_SRC))
CC =gcc
$(TGT): $(OBJ)
$(CC) -o $@ $^
clean:
$(RM) $(TGT) *.o
编译与运行
编译后生成可执行文件main
运行main
,结果如下:
分析结果
可以看到,我们成功地在C程序中引用了a.s
里面定义的符号(或者说变量)phone_num
.
注意:
1. phone_num
的地址是在链接后确定的。如果想查看符号地址,可以用nm
命令。
nm main
- 标识符
phone_num
,在汇编语言中代表一个内存地址;但是在C语言中,则表示一个变量,读写这个变量时,表示读写内存地址 0x601038 处存放的数据值。 - 在C语言中,要想取得
phone_num
的内存地址,则需要使用表达式&phone_num
。 - 与汇编语言相比,显然 C 语言提高了抽象层次,也造成了同一个符号在不同语言中代表不同的含义。使用时务必小心,以防混淆。
【完】