Rust内联汇编调用write系统调用报错:*const str类型不可用
Rust内联汇编调用write系统调用的问题解决
我尝试在Rust中用内联汇编执行write系统调用,重现HelloSilicon项目的Hello World示例,但传入字符串切片引用时出现矛盾错误:
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
我的代码:
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, ); } }
运行环境:MacOS v13.6,M1芯片(Armv8.5-a)
问题解答
1. 更合适的指针类型
*const str是胖指针,包含指向字符串的指针和长度两个字段,内联汇编无法直接处理这种复合类型。你需要将其转换为指向字节的裸指针*const u8,用msg.as_ptr()即可获取字符串字面量的起始字节地址,这是汇编能接受的有效指针类型。
2. 忽略的其他问题
- 系统调用号错误:MacOS ARM64的write系统调用号不是
4,而是0x2000004(MacOS的系统调用号都带有0x2000000前缀)。 - 指令使用错误:
adr X1, {msg}是错误的,adr用于获取代码段中标签的地址,但你已经把msg的指针放到寄存器里了,直接用mov X1, {msg}即可加载指针值。 - syscall触发指令错误:MacOS ARM64上触发系统调用用
svc #0,而不是svc #0x80(后者是x86架构的用法)。 - 寄存器约束优化:可以直接指定寄存器,避免额外的mov指令,让汇编更高效。
修正后的代码:
use std::arch::asm; fn main() { let msg = "Hello World!\n"; let len = msg.len(); unsafe { asm!( "mov X16, #0x2000004", // MacOS ARM64 write系统调用号 "svc #0", // 触发系统调用 in("x0") 1, // stdout文件描述符 in("x1") msg.as_ptr(), // 消息起始地址 in("x2") len, // 消息长度 ); } }
内容的提问来源于stack exchange,提问作者Max Taggart
相关产品推荐
相关产品推荐

