SBCLにプログラムの特定のポイントでCPUレジスタの値を取得させ、それを整数として出力させる方法はありますか?
gdbを使用する必要がありますか?
SBCLにプログラムの特定のポイントでCPUレジスタの値を取得させ、それを整数として出力させる方法はありますか?
gdbを使用する必要がありますか?
はい、 VOP(仮想操作)を使用してCPUレジスタにアクセスできます。VOPでは、アセンブリでもコードを記述できるため、その意味で、gcc拡張アセンブリのようなVOPを使用できます。
そこで、VOPの例とそれを実行するための関連関数を次に示します。VOPは、2つのget-cpuid-eax符号なし32ビット引数を入力として受け取り、それらをeaxとに格納し、命令をecx実行し、VOPを呼び出したto関数の後にレジスタの値を返します。次に、関数は値をに格納します。で値を簡単に印刷できます。cpuideaxcpuidget-cpuid-eaxget-cpuid-eax*result*(format t "~a" *result*)
注:このコードが常に問題なく実行されない原因となる問題(SBCLまたは私のコードのバグ?)があります。通常、再コンパイルとリロードが役立ちます。拡張アセンブリとでのx86-64アセンブリプログラムの実行のcpuid eax両方で出力を確認しました。との同じ値に対して、すべて同じ結果が得られます。gccgdbeaxecx
編集: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ライブラリからのものです。