将寄存器值读入 C 变量 [重复]

2023-12-08

我记得看到过一种使用扩展 gcc 内联汇编来读取寄存器值并将其存储到 C 变量中的方法。

但我一辈子都不记得如何形成 asm 语句。


编者注:这种使用本地寄存器asm变量的方法是现在被 GCC 记录为“不支持”。它通常仍然可以在 GCC 上运行,但会因 clang 而中断。 (我认为文档中的这个措辞是在这个答案发布后添加的。)

全局固定寄存器变量版本对于 32 位 x86 来说性能成本较大,因为 32 位 x86 只有 7 个 GP 整数寄存器(不包括堆栈指针)。这会将其减少到 6。仅当您的所有代码都大量使用全局变量时才考虑这一点。


到目前为止,与其他答案的方向不同,因为我不确定你想要什么。

GCC 手册 § 5.40 指定寄存器中的变量

register int *foo asm ("a5");

Here a5是应该使用的寄存器的名称...

当然,寄存器名称与 cpu 相关,但这不是问题,因为特定寄存器通常与显式汇编指令一起使用(请参阅扩展汇编)。这两件事通常都要求您根据 cpu 类型对程序进行条件化。

定义这样的寄存器变量并不保留寄存器;在流量控制确定变量值不存在的地方,它仍然可用于其他用途。

GCC 手册 § 3.18 代码生成约定的选项

-ffixed-reg

对待名为reg作为固定寄存器;生成的代码永远不应该引用它(除非作为堆栈指针、帧指针或其他固定角色)。

这可以以更简单的方式复制理查德的答案,

int main() {
    register int i asm("ebx");
    return i + 1;
}

虽然这毫无意义,因为你不知道里面有什么ebx登记。

如果您将这两者结合起来,请使用以下命令进行编译gcc -ffixed-ebx,

#include <stdio.h>
register int counter asm("ebx");
void check(int n) {
    if (!(n % 2 && n % 3 && n % 5)) counter++;
}
int main() {
    int i;
    counter = 0;
    for (i = 1; i <= 100; i++) check(i);
    printf("%d Hamming numbers between 1 and 100\n", counter);
    return 0;
}

您可以确保 C 变量始终使用驻留在寄存器中以便快速访问,并且不会被其他生成的代码破坏。 (方便地,ebx在通常的 x86 调用约定下是被调用者保存的,所以即使它被调用其他未编译的函数所破坏-ffixed-*,它也应该得到恢复。)

另一方面,这绝对不可移植,并且通常也不会带来性能优势,因为您限制了编译器的自由。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将寄存器值读入 C 变量 [重复] 的相关文章

随机推荐