第88回です。前回はこちら。
[第88回の様子]
2023/08/09に第88回を開催した。
内容としてはRust By Example 日本語版22. 安全でない操作の「22.1. Inline assembly」のLabelsのつづきと、Optionsの途中まで取り組んだ。ようやくインラインアセンブリの章の終わりが見えてきた...。
参加者は自分を入れて7人。
[学んだこと]
- 22.1. Inline assembly: Labels
- 前回の続きなのでサンプルコードから読んでいく。
use std::arch::asm; fn main() { let mut a = 0; unsafe { asm!( "mov {0}, 10", "2:", "sub {0}, 1", "cmp {0}, 3", "jle 2f", "jmp 2b", "2:", "add {0}, 2", out(reg) a ); } assert_eq!(a, 5); }
- アセンブリに詳しい人の解説を聞きながらコードを読んでいく
- movは代入、subは引き算、cmpは比較、jleは比較結果がless than or equals toだったらジャンプ、jmpはジャンプ
- ジャンプ先のラベルで2f、2bが指定されている
- 2のラベルが重複しているので、前後どちらに飛ぶかforward、backwardで指定するらしい
- 全体としては、10を代入して3になるまで1引いて、最後に2を足すアセンブリになっている
- 多分JavaScriptで書くとこんな感じ?whileの方が良かったかも。
var a = 10; for (; a <= 3; a--) { } a += 2; console.log(a)
- COBOL時代はこのアセンブリみたいなgoto命令を使う感じのコードがよくあった、らしい。たまにCOBOL時代を知る先輩がいて強い。
- ちなみに、アセンブリを以下のようにして重複ラベルを3つにしてもちゃんとコードが動いた
asm!( "mov {0}, 10", // a=10 "2:", "sub {0}, 1", // a-=1 "cmp {0}, 3", // if a<=3 "jle 2f", "jmp 2b", "2:", "add {0}, 5", //a+=5; "jmp 2f", "add {0}, 7", //デッドコード "2:", "add {0}, 2", out(reg) a ); // aは10になっている
- 22.1. Inline assembly: Options
- デフォルトでは、インラインアセンブリはFFIの関数呼び出しと同じように扱われれる。
- コンパイラは、これをメモリの読み書きをしたり、副作用があるものとして考える
- 最適化のために、コンパイラにより詳細なアセンブリの情報を与えるために、options()をasm!マクロの最終引数として渡すことができる
- サンプルコードは以下の通り
use std::arch::asm; let mut a: u64 = 4; let b: u64 = 4; unsafe { asm!( "add {0}, {1}", inlateout(reg) a, in(reg) b, options(pure, nomem, nostack), ); } assert_eq!(a, 8);
- コードの内容としては4に4を足すだけ
- optionの詳細な内容は時間が足りなかったので次回。
[まとめ]
モブプログラミングスタイルでRust dojoを開催した。
やっとインラインアセンブリの章が終わりそうで一安心。
今週のプルリクエストはおやすみ。