回答
是的,您可以使用VOPs (Virtual Operations)访问CPU寄存器。在VOP中,你也可以在汇编中编写代码,所以在这个意义上你可以使用VCP如gcc扩展汇编。
所以,这里有一个VOP例子和一个执行它的相关函数。所述get-cpuid-eax
VOP接收两个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的网站,我发现非常有用的,而这个编码:
the Lisp code for Dmitry Kaliyanov's article (above)
Dmitry Ignatiev's blog entry: SBCL, x86, SSE (in Russian)
Christophe Rhodes' presentation slides (pdf): Unportable but fun: Using SBCL Internals
kurohuku's blog entry: "SBCLでCPUID" (in Japanese)
swap-bytes source code file sbcl-vops.lisp
希望这有助于。
为什么你将结果存储在'* result *'中而不是返回?为什么在defun中有一个'defparameter'? “(安全0)”有特殊原因吗? – 2018-01-26 01:01:59
@DanRobertson我的答案是概念证明(可以完成),而不是企业级代码。您可以自由发布自己的答案。 – nrz 2018-01-26 06:19:14
我想我期待的答复是“如果你不做X,那么VOP不会踢” – 2018-01-26 09:59:31
cpuid示例的另一个来源(也支持64位)来自CL的优秀stmx库。
- 1. 有没有办法获得CDT中的PC寄存器值?Eclipse
- 2. 有没有办法利用所有的XMM寄存器?
- 3. 有没有办法打印SASS值输出?
- 4. 有没有办法在GDB中查看所有寄存器的特定值?
- 5. 有没有办法得到寄存器的地址?
- 6. 有没有办法让一个字大小在32位寄存器指令
- 7. 有没有办法打印SEL操作?
- 8. 有没有办法让F12工具打印出正在运行的功能?
- 9. 有没有办法在vim中区分两个寄存器?
- 10. x386,有没有办法使用另一个寄存器PUSH?
- 11. 寄存器,组件的打印值x8086
- 12. 有没有办法直接将一个寄存器的值写入文件?
- 13. 有没有办法列出UWP中连接的USB打印机?
- 14. 在GHC中,有没有办法打印模块的输出?
- 15. 有没有办法让prolog更好地打印出数据结构?
- 16. 有没有办法让我抛出异常而不打印堆栈跟踪?
- 17. 当它发出错误时,有没有办法让gcc打印违规行?
- 18. 有没有办法在Netbeans中打印一个变量的值?
- 19. 有没有办法'漂亮'打印MongoDB shell输出到文件?
- 20. 有没有办法阻止打印出一部分字符串?
- 21. 有没有办法可以打印出X509Certificate?
- 22. 有没有办法让金字塔json渲染器输出格式化,漂亮的打印输出?
- 23. SBT:有没有办法打印解析器列表?
- 24. 有没有办法让SQL Server存储过程自动出错?
- 25. CPU和内存(值,寄存器)
- 26. perf-report显示CPU寄存器的值
- 27. PHP:有没有办法打印所有已创建的对象?
- 28. 有没有办法打印JDBC执行的所有SQL语句?
- 29. 有没有办法让swi prolog打印当前的工作推理树?
- 30. 有没有办法让一个打印机的超文本链接
你需要什么用的?在Lisp函数的中间,你永远无法确定使用了什么特定的寄存器,因此打印特定寄存器的内容没有多大意义。 – 2013-03-12 02:55:54
请说明为什么您需要知道CPU寄存器的值。一般来说,知道寄存器值并不是非常有用,因为它们是由编译器管理的。在SBCL中,您可以使用汇编代码定义VOP(虚拟机操作) - 请参阅http://sbcl-internals.cliki.net/Adding%20VOPs 。 – 2013-03-12 05:52:39
我想写一个程序容易受到缓冲区溢出,并通过覆盖堆栈上的返回地址来利用它的代码。 – 2013-03-12 17:02:01