变量声明中的内联汇编语句和函数内的外部变量声明
Inline assembly statements in the variable declarations and extern variable declarations inside a function
这是 C 程序(包括内联汇编)中的一个函数,已编译并且 运行 可以使用 gcc。
- 变量声明末尾的 asm 语句是什么?
- 为什么要在函数内部声明外部变量?与在函数外声明相比有什么效果?
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
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.
分配给那个变量肯定会破坏事情,甚至阅读它也没有完全明确定义/保证的语义。当编译器修改 SP 本身为局部变量创建 space 时,为具有大量参数的函数推送参数,或者 wrt。分配。例如,如果 CSE of __stack_ptr
即使在使用 alloca
的循环中也是可能的,我也不会感到惊讶,让编译器假设 C 变量每次都具有相同的值读,如果你没有明确地写它。但我也希望你得到的任何值都在当前函数的堆栈帧中的某个位置,这与 C 程序中关于 asm 堆栈指针的有意义的说法差不多。我当然不会尝试编写执行 __stack_ptr = new_stack;
的上下文切换函数
请注意,这两种使用 asm 关键字的语法本质上是相同的:两者都在某种程度上告诉编译器:当您在正在制作的 asm 源代码中打印对此变量的引用时,请使用此名称。 (当然它必须知道它是寄存器还是符号,尤其是在 load/store 机器上而不是 CISC)。
Why is extern variable declared inside a function?
我假设只是为了限制这些声明的范围。
在普通的 ISO C 中,您可以在函数内部 extern char bar;
,编译器将引用全局变量 bar
。 (至少 gcc -Wall -Wextra -Wpedantic
没有任何抱怨,你可以从 ASM 中看到没有任何 asm()
覆盖,它使用普通的 bar
作为 asm 符号名称:https://godbolt.org/z/j1KznMEPG)
即它使用该名称引用静态存储中的变量,C 声明作用域为该函数而不是全局作用域。
(顺便说一句,函数内部的 static
var 通常有一个涉及函数名称的 asm 名称,因此它不会与另一个函数中的同名静态变量冲突。当然,这是 extern
而不是 static
,因此使用普通的全局名称是有道理的。)
这是 C 程序(包括内联汇编)中的一个函数,已编译并且 运行 可以使用 gcc。
- 变量声明末尾的 asm 语句是什么?
- 为什么要在函数内部声明外部变量?与在函数外声明相比有什么效果?
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
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.
分配给那个变量肯定会破坏事情,甚至阅读它也没有完全明确定义/保证的语义。当编译器修改 SP 本身为局部变量创建 space 时,为具有大量参数的函数推送参数,或者 wrt。分配。例如,如果 CSE of __stack_ptr
即使在使用 alloca
的循环中也是可能的,我也不会感到惊讶,让编译器假设 C 变量每次都具有相同的值读,如果你没有明确地写它。但我也希望你得到的任何值都在当前函数的堆栈帧中的某个位置,这与 C 程序中关于 asm 堆栈指针的有意义的说法差不多。我当然不会尝试编写执行 __stack_ptr = new_stack;
请注意,这两种使用 asm 关键字的语法本质上是相同的:两者都在某种程度上告诉编译器:当您在正在制作的 asm 源代码中打印对此变量的引用时,请使用此名称。 (当然它必须知道它是寄存器还是符号,尤其是在 load/store 机器上而不是 CISC)。
Why is extern variable declared inside a function?
我假设只是为了限制这些声明的范围。
在普通的 ISO C 中,您可以在函数内部 extern char bar;
,编译器将引用全局变量 bar
。 (至少 gcc -Wall -Wextra -Wpedantic
没有任何抱怨,你可以从 ASM 中看到没有任何 asm()
覆盖,它使用普通的 bar
作为 asm 符号名称:https://godbolt.org/z/j1KznMEPG)
即它使用该名称引用静态存储中的变量,C 声明作用域为该函数而不是全局作用域。
(顺便说一句,函数内部的 static
var 通常有一个涉及函数名称的 asm 名称,因此它不会与另一个函数中的同名静态变量冲突。当然,这是 extern
而不是 static
,因此使用普通的全局名称是有道理的。)