Rust内嵌汇编迁移
Rust支持内嵌汇编,当内嵌汇编语句中的指令为非AArch64架构时,需对应完成迁移,迁移过程类似于C/C++场景下的内嵌汇编迁移,可参考C/C++相关内嵌汇编移植方法,但在汇编的使用格式上有所差异。Rust是一种非常注重内存安全性的语言,对于内嵌汇编特性模块的代码,都需要放在关键字unsafe作用域下运行,同时需要启用#![feature(asm)]或#![feature(llvm_asm)]进行说明。当前Rust内嵌汇编的运用通常有以下两种形式,分别是使用asm和llvm_asm形式进行内嵌。
现象描述
源码包含x86内嵌汇编时,编译报错:error: unrecognized instruction mnemonic或error: invalid asm template modifier for this register class。
asm内嵌汇编
Rust下内嵌汇编的asm使用方式更为便捷易懂,与C/C++的内嵌汇编使用上相似,只是在实际的表示方式上存在一定差异,下面结合一小段代码进行解释说明:
asm!("rev {dst:w}, {src:w}", dst = lateout(reg)val, src = in(reg)val );

- rev:字节序反序汇编指令。
- {dst:w}/{src:w}:分别表示rev指令操作数的占位符,:w表示使用32位的w寄存器,若为:x则表示使用64位的x寄存器。
- dst = lateout(reg)val:dst为自定义的助记符,lateout表示输出(复用同一寄存器),reg表示寄存器约束,val表示实际的Rust变量。
- src = in(reg)val:src为自定义的助记符,in表示输入,reg表示寄存器约束,val表示实际的Rust变量。
示例:
以下示例针对x86下的bswap内嵌汇编指令进行移植,指令功能是对32位无符号数进行字节序反序,代码段如下:
#![feature(asm)] // x86下bswap的内嵌汇编实现 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] fn bswap(mut val : u32) -> u32 { unsafe { asm!("bswap {:e}", inout(reg)val); } return val; } // 鲲鹏下对应的内嵌汇编实现 #[cfg(any(target_arch = "aarch64"))] fn bswap(mut val : u32) -> u32 { unsafe { asm!("rev {dst:w}, {src:w}", dst = lateout(reg)val, src = in(reg)val); } return val; } fn main() { let val = bswap(32); println!("The result {}", val); }
llvm_asm内嵌汇编
Rust还可通过llvm_asm!宏使用内嵌汇编,形式与C/C++内嵌汇编规则类似,详细规则可参考http://llvm.org/docs/LangRef.html#inline-assembler-expressions,通用格式如下:
llvm_asm!(assembly template : output operands : input operands : clobbers : options );

- assembly template :汇编指令。
- output operands :输出操作数列表,多个时用逗号分开。
- input operands :输入操作数列表,多个时用逗号分开。
- clobbers :告知被修改的寄存器等资源列表(可选)。
- options :该项为rust语言特有的,多个时用逗号分开,当前支持的选项有:
- volatile ---相当于gcc/clang中__volatile__告知编译器对此内嵌汇编不做优化;
- alignstack ---告诉编译器需按特定方式进行对齐;
- intel ---使用intel语法而非默认的AT&T语法。
示例:
以下示例针对x86下bswap内嵌汇编指令进行移植,指令功能是对32位无符号数进行字节序反序。
#![feature(llvm_asm)] // x86下bswap的内嵌汇编实现 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] fn bswap(mut val : u32) -> u32 { unsafe { llvm_asm!("bswap $0" : "=r" (val) : "0" (val)); } return val; } // 鲲鹏下对应的内嵌汇编实现 #[cfg(any(target_arch = "aarch64"))] fn bswap(mut val : u32) -> u32 { unsafe { llvm_asm!( "rev ${0:w}, ${1:w}" : "=r" (val) : "r" (val)); // {dst:w}中的:w 表示使用w寄存器,若为:x则表示使用x寄存器 } return val; } fn main() { let val = bswap(32); println!("The result {}", val); }

- 内嵌汇编中的操作数使用$num来表示,如$0、$1分别对应输出和输入操作数的占位符。示例中还增加了寄存器使用类型的约束说明,如${0:w}、${1:w},其中{dst:w}中的:w表示使用32位的w寄存器,若为:x则表示使用64位的x寄存器。
- 包含内嵌汇编语句的文件编译时,均需使用rustup install nightly命令提前安装rust的nightly版本,编译时命令增加+nightly选项,如rustc +nightly main.rs。
父主题: Rust语言迁移