这是this答案的后续问题。
我正在尝试使用内联汇编将
ID_AA64MMFR1_EL1
寄存器的内容读取到 64 位变量中:
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
int main(void)
{
uint64_t foo;
__asm volatile("mov %0, ID_AA64MMFR1_EL1" : "=r"(foo) ::);
printf("%"PRIx64"\n", foo);
}
注意:我需要读取
ID_AA64MMFR1_EL1
才能知道 AFP
字段的值。
但是,汇编器拒绝此代码:
$ gcc t1b.c
/tmp/ccTDGH7d.s: Assembler messages:
/tmp/ccTDGH7d.s:22: Error: undefined symbol ID_AA64MMFR1_EL1 used as an immediate value
一个简单的问题:如何正确做?
mov
助记符仅用于在通用和/或 FP/SIMD 寄存器(x0-x30、xzr、sp、q0-q31)之间移动,以及将立即值移动到通用寄存器中。移入和移出系统寄存器分别使用 msr
和 mrs
。所以在这里你想要 mrs
而不是 mov
。
请注意,从您的标头来看,您似乎是在普通用户空间 C 程序中执行此操作。在典型的操作系统上,用户空间运行在异常级别 0 (EL0)。但
ID_AA64MMFR1_EL1
名称上的EL1标签表明它只能在EL1及更高版本(即内核模式)下读取。所以执行这条指令会陷入陷阱。
某些操作系统可能通过模拟指令来处理陷阱。我知道 Linux 对某些功能 ID 寄存器执行此操作,但不记得这是否是其中之一。但是,在这种情况下,返回到程序的值不一定等于硬件实际返回的值。例如,操作系统可以屏蔽它不想让您知道的功能位。
在其他操作系统上(例如 MacOS,如果我没记错的话),你的程序会因 SIGILL 而死掉。
通常,操作系统会提供其他类似这样的CPU特性查询机制。例如,Linux 有
/proc/cpuinfo
,MacOS 有 sysctl
。