c - 将寄存器值读入 C 变量

标签 c gcc assembly inline-assembly cpu-registers

<分区>

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

虽然我这辈子都记不起如何形成 asm 语句。

最佳答案

编者注:这种使用本地寄存器汇编变量的方式是now documented by GCC as "not supported" 。它仍然通常碰巧在 GCC 上工作,但会因 clang 而中断。 (我认为文档中的这个措辞是在发布此答案后添加的。)

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


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

GCC Manual § 5.40 Variables in Specified Registers

register int *foo asm ("a5");

Here a5 is the name of the register which should be used…

Naturally the register name is cpu-dependent, but this is not a problem, since specific registers are most often useful with explicit assembler instructions (see Extended Asm). Both of these things generally require that you conditionalize your program according to cpu type.

Defining such a register variable does not reserve the register; it remains available for other uses in places where flow control determines the variable's value is not live.

GCC Manual § 3.18 Options for Code Generation Conventions

-ffixed-reg

Treat the register named reg as a fixed register; generated code should never refer to it (except perhaps as a stack pointer, frame pointer or in some other fixed role).

这可以以更简单的方式复制 Richard 的答案,

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-* 编译的函数破坏,它也应该被恢复。)

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

关于c - 将寄存器值读入 C 变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2114163/

相关文章:

代码大小 : static inline vs inline for functions defined in header files

c - 使用 openssl 进行 Base64 解码的一个非常奇怪的错误

c++ - gcc 与 clang : expanding a captured parameter pack twice

c++ - 将两种类型组合在一起

linux - 条件 eax != 0 和 edx == 0?

assembly - 我可以在现代系统上的汇编中使用 movl 代替 movb 或 movw 吗?

c - 像一维数组一样初始化二维数组

c - 在STM32F407中断处理程序中禁用中断

c++ - 有没有办法告诉 g++ 编译器,不要在某个 -I 路径中查找包含 header ?

assembly - 我可以将 "Objdump -S -d elf-file"生成的所有部分组合成一个可重新组装的文件吗?