こんにちは、Crystal界のわるいオタクです。
Crystalみたいな低レイヤを直に触れる言語だとちょくちょくインラインアセンブラを触りたくなることもあるかと思いますが、 OutputOperands
に複数指定しようとするとなんだか構文エラーになってしまいます。
% crystal inlineasm.cr
Syntax error in inlineasm.cr:5: expecting token ')', not ':'
: "={eax}"(low), "={edx}"(high)
しょうがないのでassemblyを書いてリンクすることで回避する方法でやってみましょう。C言語で書いた静的リンクライブラリでも同じようにできるはずです。
環境は
% cat /proc/version
Linux version 3.10.0-229.14.1.el7.x86_64 (builder@kbuilder.dev.centos.org) (gcc version 4.8.3 20140911 (Red Hat 4.8.3-9) (GCC) ) #1 SMP Tue Sep 15 15:05:51 UTC 2015
% lsb_release -ds
"CentOS Linux release 7.1.1503 (Core) "
% crystal --version
Crystal 0.20.0 [b0cc6f7] (2016-11-22)
というかんじです。
まずAssembly側のコードを用意してやります。題材はrdtsc命令にします。
bits 64
global get_rdtsc
section .text
;; fun get_rdtsc(Void*)
get_rdtsc:
rdtsc
mov [rdi], eax
mov [rdi + 4], edx
ret
静的リンクライブラリを作りましょう。私の環境はLinuxなので nasm -f elf64 -o rdtsc.o rdtsc.asm
&& ar r librdtsc.a rdtsc.o
という形で作っておきます。
次にcrystal側のコードです。
@[Link("rdtsc")]
lib LibRDTSC
fun rdtsc = get_rdtsc(Void*)
end
zero = 0_u64
start = pointerof(zero)
LibRDTSC.rdtsc(start)
puts start.value
sleep(1)
fin = pointerof(zero)
LibRDTSC.rdtsc(fin)
puts fin.value
@Link(hoge)
を指定するとリンカに -lhoge
を渡してくれます。 (ドキュメント: https://crystal-lang.org/docs/syntax_and_semantics/c_bindings/lib.html)
$ crystal build --link-flags -L`pwd` rdtsc.cr
なんだかよくわからないけどちゃんと動いてるようにみえます。やったぜ。
% ./rdtsc
24892339598719468
24892342269338124