第86回です。前回はこちら。
[第86回の様子]
2023/07/26に第86回を開催した。
内容としてはRust By Example 日本語版22. 安全でない操作の「22.1. Inline assembly」のRegister template modifiersに取り組んだ。
参加者は自分を入れて7人。久しぶりにドライバを担当した!
[学んだこと]
- 22.1. Inline assembly: Register template modifiers
- レジスタの名前をテンプレート文字列に入れる際に、うまくコントロールしたい場合がある
- コンパイラはフルレジスタの名前をデフォルトで利用する
- テンプレート文字列中の修飾子を利用することで変更できる
- 以下の例では、reg_abcdクラスを使い、x86のax 、bx、cx、dxに限定している
use std::arch::asm; fn main() { let mut x: u16 = 0xab; unsafe { // レジスタ・アロケータがaxレジスタを選んだ場合、 // mov ah, alに変換され、下位ビットを上位ビットにコピーする asm!("mov {0:h}, {0:l}", inout(reg_abcd) x); } assert_eq!(x, 0xabab); }
- 試しに、
mov ah, al
と直接書いてみると、ちゃんと動いた - hやlなどのテンプレート修飾子を使わないと、以下のような警告が出る
warning: formatting may not be suitable for sub-register argument --> src/main.rs:8:19 | 8 | asm!("mov {0}, {0}", inout(reg_abcd) x); | ^^^ ^^^ - for this argument | = help: use `{0:x}` to have the register formatted as `ax` = help: or use `{0:r}` to keep the default formatting of `rax` = note: `#[warn(asm_sub_register)]` on by default
- ナビゲータの方に教えてもらい、u16の上位ビットと下位ビットを分けて出力するコードを書いてみた
- リトルエンディアンなので、下位ビットの値が配列axの先頭に入っている
use std::arch::asm; fn main() { let mut x: u16 = 0xab; let ax: [u8; 2] = unsafe { std::mem::transmute::<u16, [u8; 2]>(x) }; println!("{:?}", &ax); // [171, 0] unsafe { asm!("mov {0:h}, {0:l}", inout(reg_abcd) x); } let ax: [u8; 2] = unsafe { std::mem::transmute::<u16, [u8; 2]>(x) }; println!("{:?}", &ax); // [171, 171] assert_eq!(x, 0xabab); }
[まとめ]
モブプログラミングスタイルでRust dojoを開催した。
エンディアンとかアセンブリのインテル記法/AT&T記法とか、むずい...。
今週のプルリクエストはこちら。