【问题标题】:How to initialize a GNU C global register variable如何初始化 GNU C 全局寄存器变量
【发布时间】:2020-02-07 19:07:11
【问题描述】:

GNU C global register variables 不能有初始化器。这不会编译为 C 或 C++:

// at global scope.
register int i asm ("r12") = 10;

提供 (Godbolt) error: global register variable has initial value。本地范围当然没问题,但 GNU C local 寄存器变量是完全不同的东西。 (仅保证在与扩展 asm() 语句的交互方面做任何事情。)

代码

#include<stdio.h>
register int i asm ("r12");  //how to initialize i here?
int main()
{
    i=10;            // Would rather avoid this workaround
    printf("%d\n",i);
}

如何在全局范围内初始化i,而不是等到main的顶部?

【问题讨论】:

  • 你想解决什么问题?
  • 如果你使用libc函数,全局寄存器变量不一定会起作用。手册很清楚:使用全局寄存器变量会更改 ABI,从而使您的代码与任何库不兼容。
  • 绝对不可能将全局或静态变量放入寄存器中。但如果 i 是自动变量,则没有问题。 register int i asm ("r12")=25; 如果在函数中声明 in 则完全有效。如前所述,它的实用性值得商榷。
  • 不知道为什么我的 cmets 不断被删除,但这是最后一次。使用correct syntax 调用构造函数,但调用它的__libc_csu_init 恰好覆盖r12 值。那是因为fuz quoted“使用全局寄存器变量会更改 ABI,从而使您的代码与任何库不兼容”

标签: c gcc assembly inline-assembly cpu-registers


【解决方案1】:

你不能初始化一个全局寄存器变量。

GCC documentation 声明如下:

全局寄存器变量不能有初始值,因为可执行文件无法为寄存器提供初始内容。

还请注意以下段落:

选择寄存器时,请选择通常由机器上的函数调用保存和恢复的寄存器。这确保了不知道此保留的代码(例如库例程)将在返回之前将其恢复。

你不应该使用r12,它不会跨调用保存。

【讨论】:

  • 在 x86-64 System V 中,r12..r15 保留调用。我猜你假设这是 ARM,是的 r12 被调用破坏了。
  • @PeterCordes 我假设是 ARM。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-08
  • 1970-01-01
  • 2020-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多