內(nèi)聯(lián)匯編

2018-08-12 22:03 更新

內(nèi)聯(lián)匯編

由于低水平的操作和性能,人們希望直接控制 CPU。Rust 通過 asm!宏來支持使用內(nèi)聯(lián)匯編。語法大致匹配 GCC & Clang :

asm!(assembly template
   : output operands
   : input operands
   : clobbers
   : options
   );

任何 asm 的使用是特征封閉的(需要庫的 #![feature(asm)] 允許),當(dāng)然需要一個(gè) unsafe 塊。

注意:這里給出了 x86 和 x86-64 支持的例子,但所有平臺(tái)都支持

匯編模板

assembly template 是唯一所需的參數(shù),它必須是一個(gè)文字字符串(例如,"")

#![feature(asm)]

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
fn foo() {
unsafe {
asm!("NOP");
}
}

// other platforms
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
fn foo() { /* ... */ }

fn main() {
// ...
foo();
// ...
}

(從現(xiàn)在開始省略 feature(asm) 和 #[cfg]。)

輸出操作數(shù),輸入操作數(shù),clobber 和選擇項(xiàng)都是可選的,但是你必須添加正確的數(shù)量的 : 如果你跳過它們:

asm!("xor %eax, %eax"
:
:
: "{eax}"
   );

空格也沒有關(guān)系:

asm!("xor %eax, %eax" ::: "{eax}");

操作數(shù)

輸入和輸出操作數(shù)遵循相同的格式:"constraints1"(expr1), "constraints2"(expr2), ..."。輸出操作數(shù)表達(dá)式必須是可變左值,或者沒有分配內(nèi)存:

fn add(a: i32, b: i32) -> i32 {
let c: i32;
unsafe {
asm!("add $2, $0"
 : "=r"(c)
 : "0"(a), "r"(b)
 );
}
c
}

fn main() {
assert_eq!(add(3, 14159), 14162)
}

如果你想在這個(gè)位置上使用真正的操作數(shù),然而,你需要把花括號(hào) { } 放在你想要的的寄存器兩邊,你需要加具體操作數(shù)的大小。對(duì)于低水平的編程這是非常有用的,在程序中使用哪個(gè)寄存器很重要:

let result: u8;
asm!("in %dx, %al" : "={al}"(result) : "{dx}"(port));
result

Clobbers    

一些指令修改有可能持有不同值的寄存器,所以我們使用超時(shí)列表來指示編譯器不承擔(dān)加載到寄存器將保持有效的任何值。

// Put the value 0x200 in eax
asm!("mov $$0x200, %eax" : /* no outputs */ : /* no inputs */ : "{eax}");

輸入和輸出寄存器不需要被列出來,因?yàn)樾畔⒁呀?jīng)被給定約束傳達(dá)。否則,任何其他被隱式或顯式地使用的寄存器應(yīng)該列出?!   ?/p>

如果內(nèi)聯(lián)會(huì)更改代碼寄存器, cc 應(yīng)該指定為一個(gè) clobber。同樣,如果內(nèi)聯(lián)會(huì)修改內(nèi)存,memory 還應(yīng)該被指定。

選擇項(xiàng)

最后一部分,options 是 Rust 特有的。形式是逗號(hào)分隔字符串(例如::"foo", "bar", "baz")。這是用于指定內(nèi)聯(lián)匯編的一些額外的信息:    

當(dāng)前有效的選項(xiàng)是:    

  1. volatile -這類似于在 gcc/clang 中指定_ _asm__ __volatile__(...) ?! ?/li>
  2. alignstack-某些指定堆的對(duì)齊某種方式(例如,SSE)的指令并說明這個(gè)指示編譯器插入其通常堆棧對(duì)齊的代碼的指令?!?/li>
  3. intel -使用 intel 語法而不是默認(rèn)的 AT&T。

      let result: i32;
      unsafe {
         asm!("mov eax, 2" : "=`{eax}"(result) : : : "intel")
      }  println!("eax is currently {}", result);
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)