Sam*_*ard 8 assembly x86-64 sbcl common-lisp cpu-registers
有没有办法让SBCL在我的程序中的某一点获取CPU寄存器的值并将其打印为整数?
我必须使用gdb吗?
nrz*_*nrz 11
是的,您可以使用VOP(虚拟操作)访问CPU寄存器.在VOP中你也可以在汇编中编写代码,所以在这个意义上你可以使用像gcc扩展汇编这样的VOP.
所以,这是一个示例VOP和执行它的相关函数.该get-cpuid-eaxVOP接收两个32位无符号的参数作为输入,将它们存储在eax和ecx,执行cpuid指令,并返回的值eax之后寄存器中的cpuid到get-cpuid-eax函数调用该VOP.get-cpuid-eax然后该函数将值存储在*result*.您可以轻松打印该值(format t "~a" *result*).
注意:有一些问题(SBCL或我的代码中的错误?)导致此代码不会始终没有问题地执行.重新编译和重新加载通常有帮助.我已经证实了cpuid eax具有输出gcc扩展组装和运行中的x86-64汇编程序gdb.这一切都使在相同的值相同的结果eax和ecx.
编辑:更改功能和VOP名称get-cpuid-eax以避免与变量名称混淆.
编辑:使用slimv修复代码格式.
(sb-vm::defknown get-cpuid-eax
((unsigned-byte 32) (unsigned-byte 32))
(unsigned-byte 32)
(sb-c::foldable sb-c::flushable sb-c::movable))
(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)
(:temporary
(:sc sb-vm::unsigned-reg :offset sb-vm::eax-offset)
eax)
(:temporary
(:sc sb-vm::unsigned-reg :offset sb-vm::ecx-offset)
ecx)
(:results
(my-result :scs (sb-vm::unsigned-reg)))
(:result-types sb-vm::unsigned-num)
(:generator
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)
(declare (type (unsigned-byte 32) my-eax my-ecx)
(optimize (speed 3) (safety 0)))
(defparameter *result* (get-cpuid-eax my-eax my-ecx)))
一些具有短VOP的网站,我发现在编写此代码时非常有用:
梅德Kaliyanov的文章"ДобавлениепримитивоввиртуальноймашиныSBCL"("添加SBCL的原始虚拟机",在俄语)
Dmitry Kaliyanov的文章(上图)的Lisp代码
Dmitry Ignatiev的博客文章:SBCL,x86,SSE(俄文)
Christophe Rhodes的演示幻灯片(pdf):不可移植但有趣:使用SBCL内部
kurohuku的博客文章:"SBCLでCPUID"(日文)
希望这可以帮助.