7

有没有办法让 SBCL 在我的程序中的某个点获取 CPU 寄存器的值并将其打印为整数?

我必须使用gdb吗?

4

2 回答 2

10

是的,您可以使用VOP(虚拟操作)访问 CPU 寄存器。在 VOP 中,您也可以在汇编中编写代码,因此从这个意义上说,您可以使用像 gcc 扩展汇编这样的 VOP。

因此,这是一个示例 VOP 和执行它的相关函数。VOP 接收两个无get-cpuid-eax符号 32 位参数作为输入,将它们存储在eaxand中ecx,执行cpuid指令,并在调用 VOP的to函数eax之后返回寄存器的值。然后该函数将值存储在. 您可以使用 轻松打印该值。cpuidget-cpuid-eaxget-cpuid-eax*result*(format t "~a" *result*)

注意:有一些问题(SBCL 或我的代码中的错误?)导致此代码始终无法正常执行。重新编译和重新加载通常会有所帮助。我已经确认了扩展程序集的cpuid eax输出并在. 对于和中的相同值,所有结果都相同。gccgdbeaxecx

编辑:更改函数和 VOP 名称以get-cpuid-eax避免与变量名称混淆。

编辑:使用 slimv 修复代码格式。

(sb-vm::defknown get-cpuid-eax
                 ((无符号字节 32) (无符号字节 32))
                 (无符号字节 32)
                 (sb-c::foldable sb-c::flushable sb-c::movable))

(sb-vm::define-vop (get-cpuid-eax)
  (:政策:快速安全)
  (: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)
  (:结果
    (我的结果: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)
  (声明(类型(无符号字节 32)my-eax my-ecx)
           (优化(速度 3)(安全 0)))
  (defparameter *result* (get-cpuid-eax my-eax my-ecx)))

我发现一些 VOP 很短的网站在编写代码时非常有用:

Dmitry Kaliyanov 的文章“Добавление примитивов виртуальной машины SBCL”(“添加 SBCL 的原始虚拟机”,俄语)

Dmitry Kaliyanov 文章的 Lisp 代码(上图)

Dmitry Ignatiev 的博客条目:SBCL、x86、SSE(俄语)

Christophe Rhodes 的演示幻灯片 (pdf):不便携但很有趣:使用 SBCL 内部

kurohuku 的博客条目:“SBCLでCPUID”(日文)

交换字节源代码文件 sbcl-vops.lisp

希望这可以帮助。

于 2013-03-12T23:50:04.530 回答
1

cpuid 示例的另一个来源(也支持 64 位)来自优秀的 stmx CL 库。

于 2018-01-25T09:28:42.890 回答