Search code examples
assemblyrustinline-assembly

How to pass in &str when using rust asm! inline assembly


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

  • Explicit registers are string literals so they cannot come from a function parameter, a variable or even a constant but they must be typed directly when calling the asm! macro.

    This makes sense since the compiler has to emit different binary code depending on the chosen register, and so must know the chosen register at compile time.