I am trying to execute a write
syscall using inline assembly in Rust. Basically I'm trying to reproduce this hello world example. I'm trying to pass in a reference to a string slice as my message, but I'm getting the following error which seems to contradict its self:
cannot use value of type `*const str` for inline assembly
only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
The code is below, but my questions are:
*const str
?use std::arch::asm;
fn main() {
let msg = "Hello World!\n";
let len = msg.len();
unsafe {
asm!(
"mov X0, #1", // specify stdout
"adr X1, {msg}", // point to message
"mov X2, {len}", // specify message length
"mov X16, #4", // specify syscall number for 'write'
"svc #0x80", // syscall
msg = in(reg) msg,
len = in(reg) len,
);
}
}
This is running on MacOS v13.6, on an M1 chip (Armv8.5-a).
Well there is a slight difference between &str
which is a wide reference, *const str
a wide pointer and a thin pointer as required by the assembly. Though the error message could make the requirement for a thin pointer clearer. Fortunately there is a method to turn a &str
into an apropriate pointer unsurprisingly called as_ptr
use std::arch::asm;
fn main() {
let msg_str = "Hello World!\n";
let len = msg_str.len();
let msg = msg_str.as_ptr();
unsafe {
asm!(
"mov X0, #1", // specify stdout
"adr X1, {msg}", // point to message
"mov X2, {len}", // specify message length
"mov X16, #4", // specify syscall number for 'write'
"svc #0x80", // syscall
msg = in(reg) msg,
len = in(reg) len,
);
}
}
Does get further, but I can't test the arm assembly so it still fails to compile for me.