【问题标题】:Inline assembly statements in the variable declarations and extern variable declarations inside a function变量声明中的内联汇编语句和函数内部的外部变量声明
【发布时间】:2021-06-01 01:13:05
【问题描述】:

这是C程序(包括内联汇编)中的一个函数,用gcc编译并运行正常。

  1. 变量声明末尾的 asm 语句是什么?
  2. 为什么在函数内部声明外部变量?与在函数外声明相比有什么效果?
extern unsigned char __heap_base;
extern unsigned char __heap_limit;

caddr_t _sbrk_r (struct _reent *r,int incr)
{
extern   unsigned char  __bottom_of_heap asm ("__heap_base");
extern   unsigned char  __limit_of_heap  asm ("__heap_limit");
register unsigned char *__stack_ptr  asm ("sp");
...
}

在另一个汇编文件中,__heap_base、__heap_limit 定义如下(摘录)。

                .global  __heap_base
                .global  __heap_limit

__user_thread_space:
                .equ     __heap_base,  __user_thread_space + THREAD_AREA
                .equ     __heap_limit, __heap_base         + HEAP_SIZE

【问题讨论】:

  • 你从哪里得到这个代码?
  • 它来自我的同事,我认为它是 arm 为启动代码提供的。

标签: c gcc inline-assembly


【解决方案1】:

https://gcc.gnu.org/onlinedocs/gcc/Asm-Labels.html 正在为这些 C 变量设置 asm 符号名称。这使您可以设置 asm 名称,而不管编译器是否通常预先添加一个额外的 _,例如,或者覆盖 C++ 名称修饰。或者在这种情况下,只需使用与 C var 名称不同的 asm 符号名称。


堆栈指针的register ... asm("regname") 全局变量也记录在案:https://gcc.gnu.org/onlinedocs/gcc/Global-Register-Variables.html

分配给该变量肯定会破坏事情,即使阅读它也没有完全定义/保证的语义wrt。当编译器修改 SP 本身为本地人腾出空间时,为具有大量 args 或 wrt 的函数推送 args。阿洛卡。例如,即使在使用alloca 的循环中,如果__stack_ptrCSE__stack_ptr 是可能的,我也不会感到惊讶,让编译器假设一个C 变量在每次读取时都具有相同的值,如果你不这样做' t 明确地写出来。但我也希望你得到的任何值都在当前函数的堆栈帧中的某个位置,这与 C 程序中的 asm 堆栈指针的意义差不多。我当然不会尝试编写 __stack_ptr = new_stack;

那样的上下文切换函数

请注意,asm 关键字的这两种用法的语法本质上是相同的:两者都在告诉编译器:当您在创建的 asm 源中打印对此变量的引用时,请使用此名称。 (当然它必须知道它是寄存器还是符号,尤其是在加载/存储机器而不是 CISC 上)。


为什么要在函数内部声明外部变量?

我假设只是为了限制这些声明的范围。

在普通的 ISO C 中,您可以在函数内部使用 extern char bar;,编译器将引用全局变量 bar。 (至少gcc -Wall -Wextra -Wpedantic没有任何抱怨,你可以从ASM看到没有任何asm()覆盖,它使用普通的bar作为asm符号名称:https://godbolt.org/z/j1KznMEPG

即它使用该名称引用静态存储中的一个变量,C 声明的范围是这个函数而不是全局范围。

(顺便说一句,函数内部的static var 通常有一个涉及函数名称的asm 名称,因此它不会与另一个函数中的同名静态var 冲突。当然,这是@987654337 @ 不是 static,所以使用普通的全局名称是有道理的。)

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2013-03-23
  • 1970-01-01
  • 2012-02-06
  • 1970-01-01
  • 2017-06-09
  • 2023-04-03
相关资源
最近更新 更多