第87回です。前回はこちら。
[第87回の様子]
2023/08/02に第87回を開催した。
内容としてはRust By Example 日本語版22. 安全でない操作の「22.1. Inline assembly」のMemory address operandsとLabelsの途中まで取り組んだ。
参加者は自分を入れて6人。
そろそろ教材が終わりそうなので、次はHaskell dojoをやろうか、などと話している今日この頃。
[学んだこと]
- 22.1. Inline assembly: Memory address operands
- アセンブリで、場合によってはメモリアドレスが必要になる
- Intelのx86/x86_64では[]を使ってメモリオペランドであることを示す
use std::arch::asm; fn load_fpu_control_word(control: u16) { unsafe { asm!("fldcw [{}]", in(reg) &control, options(nostack)); } }
- fldcwは浮動小数点の丸めの設定をする命令らしい
- それらしいコードを何度か試してみたが、うまく出力を変えることができなかった...
use std::arch::asm; fn load_fpu_control_word(control: u16) { unsafe { asm!("fldcw [{}]", in(reg) &control, options(nostack)); } } fn calc() -> f64 { 1.0 / 0.3 } fn main() { let a = calc(); println!("a: {a}"); // a: 3.3333333333333335 // let round_up = 0x1b3a; let round_down = 0x173a; load_fpu_control_word(round_down); let b = calc(); println!("b: {b}"); // b: 3.3333333333333335 }
- これだと[]でメモリアドレスを見れているかわからなかったのでmov命令で書き直してみた
use std::arch::asm; fn f(input: &i32) -> i32 { let ret: i32; unsafe { asm!("mov {}, [{}]", out(reg) ret, in(reg) input, ); } ret } fn main() { let a = 100; let b = f(&a); println!("b: {b}"); // b: 100 }
- 22.1. Inline assembly: Labels
- アセンブリのラベルの話。
- ラベルを再利用すると、アセンブラまたはリンカーのエラーが発生したり、奇妙な挙動が発生してしまう可能性がある
- 再利用にはいくつかのパターンがある
- 明示的にasm!ブロック内やasm!ブロック間で複数回利用する場合
- asm!のインライン化で暗黙的に複数回利用される場合
- LTO(Link Time Optimization?)他のクレートのコードによって暗黙的に利用される場合
- ラベルでシンボルを定義するとエラーになる可能性があるので、数値のローカルラベルのみ利用可能
- さらに、Intelのx86の場合、LLVMのバグで0や1だけからなるラベル(0、11、101010)はバイナリ値として扱われるため利用できない
- options(att_syntax)を使うとこの問題を回避できるが、asm!ブロックの書き方に影響するので要注意
- サンプルコードが書かれていたが今回は時間切れ。次回に持ち越し...
[まとめ]
モブプログラミングスタイルでRust dojoを開催した。
プロセッサによって色々違うんだなあ...。
今週のプルリクエストはおやすみ。