基于文档和汇编知识的解释
在 GNU ARM 汇编器中,.extern 用于声明一个外部符号,即这个符号在当前汇编文件中被引用,但在其他文件中定义。
1. 基本语法格式
.extern symbol_name
或
.extern symbol_name[, size]
2. 功能说明
- 告诉汇编器:
symbol_name这个符号是在其他模块(其他汇编文件或C文件)中定义的 - 当前文件只是引用这个符号
- 链接器会在链接阶段解析这个符号的实际地址
3. 实际使用示例
示例1:基本用法
# 声明外部函数
.extern printf
.extern main
# 声明外部变量
.extern global_variable
.extern buffer, 1024 # 可选的size参数
.section .text
_start:
# 调用外部函数
bl main
bl printf
# 访问外部变量
ldr r0, =global_variable
ldr r1, [r0]
示例2:在 ARM 汇编中的典型应用
# 声明C语言中定义的函数和变量
.extern SystemInit
.extern main
.extern _estack
.extern _sdata
.extern _edata
.section .text
.global _start
_start:
# 设置栈指针(使用外部定义的栈顶)
ldr sp, =_estack
# 调用C函数
bl SystemInit
bl main
b .
4. 在 C 和汇编混合编程中的应用
C 代码(example.c):
// 定义全局变量和函数
int global_var = 42;
void c_function(void) {
// 函数实现
}
汇编代码(example.s):
# 声明C中定义的符号
.extern global_var
.extern c_function
.section .text
.global asm_function
asm_function:
# 访问C全局变量
ldr r0, =global_var
ldr r1, [r0]
# 调用C函数
bl c_function
bx lr
5. 注意事项
可选的 size 参数:某些 GNU 汇编器版本支持指定符号大小
.extern buffer, 256 # 声明一个256字节的外部缓冲区多个声明:可以多次声明同一个外部符号,不会产生错误
.extern printf .extern printf # 重复声明,允许但不必要与
.global的区别:.extern:声明”我需要这个符号,它在别处定义”.global:声明”我定义了这个符号,别人可以使用”
现代 GNU 汇编器的用法:
.extern通常可以省略,因为汇编器会自动将未定义的引用视为外部符号。但显式使用可以提高代码可读性。
总结
在 GNU ARM 汇编中,.extern 伪指令用于声明外部符号,是模块化编程和 C/汇编混合编程的重要工具。它告诉汇编器和链接器某个符号在其他模块中定义,当前模块只是引用它。虽然在某些情况下可以省略,但显式声明可以使代码意图更清晰,便于维护和调试。
