回答
是的,您可以使用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