SBCLにプログラムの特定のポイントでCPUレジスタの値を取得させ、それを整数として出力させる方法はありますか?
gdbを使用する必要がありますか?
SBCLにプログラムの特定のポイントでCPUレジスタの値を取得させ、それを整数として出力させる方法はありますか?
gdbを使用する必要がありますか?
はい、 VOP(仮想操作)を使用してCPUレジスタにアクセスできます。VOPでは、アセンブリでもコードを記述できるため、その意味で、gcc拡張アセンブリのようなVOPを使用できます。
そこで、VOPの例とそれを実行するための関連関数を次に示します。VOPは、2つのget-cpuid-eax
符号なし32ビット引数を入力として受け取り、それらをeax
とに格納し、命令をecx
実行し、VOPを呼び出したto関数の後にレジスタの値を返します。次に、関数は値をに格納します。で値を簡単に印刷できます。cpuid
eax
cpuid
get-cpuid-eax
get-cpuid-eax
*result*
(format t "~a" *result*)
注:このコードが常に問題なく実行されない原因となる問題(SBCLまたは私のコードのバグ?)があります。通常、再コンパイルとリロードが役立ちます。拡張アセンブリとでのx86-64アセンブリプログラムの実行のcpuid
eax
両方で出力を確認しました。との同じ値に対して、すべて同じ結果が得られます。gcc
gdb
eax
ecx
編集:get-cpuid-eax
変数名との混同を避けるために関数とVOP名を変更しました。
編集: slimvでのコードフォーマットを修正しました。
(sb-vm :: defknown get-cpuid-eax ((unsigned-byte 32)(unsigned-byte 32)) (unsigned-byte 32) (sb-c ::foldable sb-c :: flushable sb-c :: moveable)) (sb-vm :: define-vop(get-cpuid-eax) (:policy:fast-safe) (:translate get-cpuid-eax) (:args (my-eax:scs(sb-vm :: unsigned-reg):target eax) (my-ecx:scs(sb-vm :: unsigned-reg):target ecx)) (:arg-types sb-vm :: unsigned-num sb-vm :: unsigned-num) (:一時的 (:sc sb-vm :: unsigned-reg:offset sb-vm :: eax-offset) eax) (:一時的 (:sc sb-vm :: unsigned-reg:offset sb-vm :: ecx-offset) ecx) (:結果 (my-result:scs(sb-vm :: unsigned-reg))) (:result-types sb-vm :: unsigned-num) (:発生器 0 (sb-vm :: move eax my-eax) (sb-vm :: move ecx my-ecx) (sb-vm :: inst cpuid) (sb-vm :: move my-result eax))) (defun get-cpuid-eax(my-eax my-ecx) (宣言(type(unsigned-byte 32)my-eax my-ecx) (最適化(速度3)(安全0))) (defparameter * result *(get-cpuid-eax my-eax my-ecx)))
これをコーディングするときに非常に便利だと思った短いVOPを持ついくつかのWebサイト:
Dmitry Kaliyanovの記事「ДобавлениепримитивоввиртуальноймашиныSBCL」(「SBCLのプリミティブ仮想マシンの追加」、ロシア語)
Dmitry Kaliyanovの記事のLispコード(上記)
Dmitry Ignatievのブログエントリ:SBCL、x86、SSE(ロシア語)
Christophe Rhodesのプレゼンテーションスライド(pdf):移植性はないが楽しい:SBCL内部の使用
swap-bytesソースコードファイルsbcl-vops.lisp
お役に立てれば。
cpuidの例(64ビットもサポート)のもう1つのソースは、CL用の優れたstmxライブラリからのものです。