中文
注册
我要评分
文档获取效率
文档正确性
内容完整性
文档易理解
在线提单
论坛求助

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。