kdnakt blog

hello there.

Rust dojo第81回を開催した

第81回です。前回はこちら。 

kdnakt.hatenablog.com

 

[第81回の様子]

2023/06/14に第81回を開催した。

内容としてはRust By Example 日本語版22. 安全でない操作の「22.1. Inline assembly」のExplicit register operandsに取り組んだ。
参加者は自分を入れて多分6~7人。今回は低レイヤに詳しい別のくわしい人がドライバやってくれたので助かった!

[学んだこと]

use std::arch::asm;

let cmd = 0xd1;
unsafe {
// 0x64ポートに0xd1を出力する asm!("out 0x64, eax", in("eax") cmd); }
  • 明示的にレジスタを指定する場合、インラインアセンブリの中でテンプレート文字列として変数を利用できないので、上のようにレジスタ名を直接書く必要がある
  • また、レジスタを明示的に指定した場合は、オペランドのリスト(引数のリスト)の末尾に来る必要がある
  • x86のmul命令を利用した例は以下のようになる
use std::arch::asm;

fn mul(a: u64, b: u64) -> u128 {
    println!("a={:X}", a);
    println!("b={:X}", b);
    let lo: u64;
    let hi: u64;

    unsafe {
        asm!(
            // x86のmul命令はraxレジスタを暗黙の入力に利用する
            // raxとrdxレジスタに128ビットの計算結果を出力する
            "mul {}",
            in(reg) a,
            // raxレジスタにbを入力し、出力はlo変数に戻す
            inlateout("rax") b => lo,
            // raxの上位64ビットはrdxレジスタにあり、hi変数に戻される
            lateout("rdx") hi
        );
    }

    ((hi as u128) << 64) + lo as u128
}

fn main() {
    let res = mul(u64::MAX, u64::MAX);
    // a=FFFFFFFFFFFFFFFF
    // b=FFFFFFFFFFFFFFFF

    println!("res={:X}", res);
    // res=FFFFFFFFFFFFFFFE0000000000000001
}
  • テキストには載っていなかったが、ドライバの人が詳しかったのでxor命令も説明してくれた
  • xorの結果を返すので、どんな値が与えられても0になる
use std::arch::asm;

fn main() {
    let mut cmd = 1;
    println!("cmd={}", cmd); // cmd=1
    unsafe {
        asm!("xor eax, eax", inout("eax") cmd);
    }
    println!("cmd={}", cmd); // cmd=0
}
  • この例は最近読んでいるRust Atomics and Locksでも登場していた
    • mov eax, 0とやるよりも必要なレジスタの数が少なくてすむので好まれるとのこと

Rust Atomics and Locks — Chapter 7. Understanding the Processor

[まとめ]

モブプログラミングスタイルでRust dojoを開催した。
レジスタむずい...低レイヤーほんとに何もわからない。

今週のプルリクエストはおやすみ。