Rustのインラインアセンブリについて
#Rust
reference: https://doc.rust-lang.org/reference/inline-assembly.html
example: https://doc.rust-jp.rs/rust-by-example-ja/unsafe/asm.html
Cのインラインアセンブリ
code:riscv.s
__asm__ __volatile__("ecall"
: "=r"(a0), "=r"(a1) // 出力オペランド
: "r"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5), "r"(a6), "r"(a7) // 入力オペランド
: "memory"); // メモリ領域が変更される
命令、出力オペランド、入力オペランド、破壊されるレジスタの4項目の指定ができる
"ダブルクォートでくくられている部分は「制約」で、rは汎用レジスタ、=は書き込み可能を表す
https://bamboo-cpu.hatenablog.com/entry/2020/12/03/215111 わかりやすい記事
破壊されるレジスタの部分は、変更が行われる部分をコンパイラに知らせている
コンパイラは必要に応じて、レジスタなどの退避を行うらしい
ここはちゃんと理解していない
Rustのインラインアセンブリ
基本的には、Cのインラインアセンブリと対応している
code:riscv.rs
asm!(
"ecall",
inout("a0") arg0,
inout("a1") arg1,
out("a2") arg2,
out("a3") arg3,
out("a4") arg4,
out("a5") arg5,
out("a6") fid,
out("a7") eid,
);
入力、出力のオペランドについては、たぶん同じ?
https://doc.rust-lang.org/reference/inline-assembly.html#operand-type 詳しくはココ
inoutは、inとoutで同じレジスタが使われることが保証される。また、mutableである必要がある
outは、mutableでないとコンパイルエラーになった(ドキュメントに「最後に書き込まれる」とあるためか?)
レジスタの指定について
https://doc.rust-lang.org/reference/inline-assembly.html#register-operands ここに書いてある
普通に使うレジスタは全部使えそう
ただし、アーキテクチャによって、レジスタに渡せる型に違いがある
https://doc.rust-lang.org/reference/inline-assembly.html#register-names レジスタの指定の仕方はここ
riscvだとx10をa0のような、対応している別名(エイリアス?)として使える
破壊されるレジスタについて
https://doc.rust-lang.org/reference/inline-assembly.html#options
nomemのところを見ると、メモリを変更しないことを保証する的なことが書いてあるため、デフォルトではメモリは変更される前提らしい
https://doc.rust-jp.rs/rust-by-example-ja/unsafe/asm.html#オプション ここに同様のことが書いてあった
Cのインラインアセンブリと対応させるときは、ちゃんと調べる必要あり