【问题标题】:Reading registers in the GCC using a char pointer使用 char 指针读取 GCC 中的寄存器
【发布时间】:2020-05-27 09:28:39
【问题描述】:

我最近开始学习如何在 C 代码中使用内联汇编,并发现了一个有趣的功能,您可以在其中为局部变量指定寄存器 (https://gcc.gnu.org/onlinedocs/gcc/Local-Register-Variables.html#Local-Register-Variables)。

该功能的使用方法如下:

register int *foo asm ("r12");

然后我开始怀疑是否可以插入一个char指针,例如

const char d[4] = "r12";
register int *foo asm (d);

但得到了error: expected string literal before ‘d’(如预期的那样)

我可以理解为什么这是一个不好的做法,但是有没有可能的方法来实现类似的效果,我可以使用 char 指针来访问寄存器?如果不是,除了潜在的安全问题之外,还有什么特别的原因不允许这样做吗?

另外,我阅读了这个 StackOverflow 问题:String literals: pointer vs. char array

谢谢。

【问题讨论】:

  • 根据文档,register int *foo asm ("r12"); 显然告诉编译器它应该使用寄存器r12 来存储变量foo,因此它会影响编译器发出的汇编代码。另一方面,register int *foo asm (d); 意味着“将变量 foo 存储在编译时未知的特定寄存器中”,这对我来说似乎是不可能的。

标签: c gcc assembly inline-assembly


【解决方案1】:

初始化变量的语法是register char *foo asm ("r12") = d;,将asm-register变量指向一个字符串。您不能使用运行时变量字符串作为寄存器名称;寄存器选择必须在编译时组装成机器代码。

如果这就是您想要做的,那么您就误解了关于汇编语言和/或提前编译的语言如何编译成机器代码的一些基本知识。 GCC 不会生成自修改代码(即使它愿意,安全地这样做也需要重做由提前优化器完成的寄存器分配),或者基于字符串重新 JIT 自身的代码。

(我第一次看你的问题时,我什至不明白你在做什么,因为我只考虑可能的事情。@FelixG 的评论是我理解这个问题所需的线索.)


(还请注意,寄存器不可索引;即使在 asm 中,您也不能使用单个指令来读取由另一个寄存器中的整数选择的寄存器编号。您可以在其上进行分支,或将所有寄存器存储在内存中和索引,就像可变参数函数对其传入的寄存器 args 所做的那样。)

如果您确实想要一个编译时常量字符串文字,只需使用正常语法即可。如果您想要初始化相同的字符串,请使用 CPP 宏一个字符数组。

【讨论】:

    猜你喜欢
    • 2013-05-21
    • 2013-03-21
    • 2022-01-24
    • 1970-01-01
    • 1970-01-01
    • 2015-01-25
    • 1970-01-01
    • 2016-07-14
    相关资源
    最近更新 更多