I want this function to operate the register with the specified name, but it seems that the asm! macro does not support it?
pub fn read_cpuid(reg: &str) -> u64 {
let val: u64;
unsafe {
asm!("mrs {}, {}",
out(reg) val,
reg
);
}
val
}
The error message is as follows:
error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `r`
If I change r to pass it in using reg, it still doesn’t work.
use core::arch::asm;
pub fn read_cpuid(r: &str) -> u64 {
let val: u64;
unsafe {
asm!("mrs {}, {}",
out(reg) val,
in(reg) r
);
}
val
}
error: cannot use value of type `*const str` for inline assembly
note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
I can only use enumeration to solve it now, but the scalability of this approach is too poor. Is there a better way?
>Solution :
*const str is a "fat" pointer, meaning it stores the length of the str alongside the pointer to the beginning of the str. Therefore, it can’t fit within a single register.
Use str::as_ptr so get a *const u8 which is just a pointer.
use core::arch::asm;
pub fn read_cpuid(r: &str) -> u64 {
let val: u64;
unsafe {
asm!("mrs {}, {}",
out(reg) val,
in(reg) r.as_ptr()
);
}
val
}
This error message is not great. I recommend opening an issue suggesting that the diagnostic be improved.