---
title: Rust内嵌汇编迁移
description: "Rust支持内嵌汇编，当内嵌汇编语句中的指令为非AArch64架构时，需对应完成迁移，迁移过程类似于C/C++场景下的内嵌汇编迁移，可参考C/C++相关内嵌汇编移植方法，但在汇编的使用格式上有所差异。Rust是一种非常注重内存安全性的语言，对于内嵌汇编特性模块的代码，都需要放在关键字unsafe作用域下运行，同时需要启用#![feature(asm)]或#![feature(llvm_asm)]进行说明。当前Rust内嵌汇编的运用通常有以下两种形式，分别是使用asm和llvm_asm形式进行内嵌。"
url: https://www.hikunpeng.com/document/detail/zh/kunpenggrf/codeprtr/kunpengtaishanporting_12_0099.html
sourcePath: /source/zh/kunpenggrf/codeprtr/kunpengtaishanporting_12_0099.html
indexId: 9b8bf73eb58ed69911b349a4b6b815360f6d96ec933ee0c91fdcbf580594668f65
---
# 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(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。
