第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を開催した。
プロセッサによって色々違うんだなあ...。
今週のプルリクエストはおやすみ。