第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記法とか、むずい...。
今週のプルリクエストはこちら。