C'è un modo per far sì che SBCL acquisisca il valore di un registro CPU in un determinato punto del mio programma e lo stampi come un intero?C'è un modo per far sì che sbcl stampi il valore di un registro della CPU?
Devo usare gdb?
C'è un modo per far sì che SBCL acquisisca il valore di un registro CPU in un determinato punto del mio programma e lo stampi come un intero?C'è un modo per far sì che sbcl stampi il valore di un registro della CPU?
Devo usare gdb?
Sì, è possibile accedere ai registri della CPU utilizzando VOPs (Virtual Operations). In VOP è possibile scrivere codice anche in assembly, quindi in questo senso è possibile utilizzare VOP come l'assembly esteso di gcc.
Quindi, ecco un esempio di VOP e una funzione correlata per eseguirlo. Il get-cpuid-eax
VOP riceve due argomenti senza segno a 32 bit come input, li memorizza in eax
e ecx
, esegue cpuid
istruzione, e restituisce il valore di registro eax
dopo la funzione cpuid
a get-cpuid-eax
che ha chiamato il VOP. La funzione get-cpuid-eax
memorizza quindi il valore in *result*
. È possibile stampare facilmente il valore con (format t "~a" *result*)
.
Nota: c'è qualche problema (bug in SBCL o nel mio codice?) Che causa questo codice da non eseguire senza problemi sempre. Solitamente la ricompilazione e il ricaricamento aiutano. Ho confermato l'uscita cpuid
eax
con l'assembly esteso gcc
ed eseguendo un programma di assemblaggio x86-64 in gdb
. Tutti danno gli stessi risultati per gli stessi valori in eax
e ecx
.
Edit: cambiato funzione & VOP nomi ai get-cpuid-eax
per evitare confusione con i nomi delle variabili.
Modifica: formattazione codice fisso con 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)))
Alcuni siti web con brevi VOP che ho trovato molto utile durante la codifica questo:
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
Spero che questo aiuti.
Perché stai memorizzando il risultato in '* risultato *' invece di restituirlo? E perché un 'defparameter' all'interno di un' defun' ?! E c'è una ragione particolare per avere '(sicurezza 0)'? –
@DanRobertson La mia risposta è una dimostrazione del concetto (che si può fare), non un codice a livello di impresa. Sei libero di pubblicare la tua risposta. – nrz
Suppongo che mi aspettassi una risposta del tipo "se non fai X allora il vop non kickerà" –
Un'altra fonte di un esempio di cpuid (che supporta anche 64 bit) proviene dall'eccellente libreria stmx per CL.
Che cosa avete bisogno di questo per? Nel bel mezzo di una funzione Lisp, non si può mai essere sicuri di quale sia lo specifico registro utilizzato per cui stampare il contenuto di un registro specifico non avrebbe molto senso. –
Si prega di chiarire perché è necessario conoscere il valore di un registro CPU. In generale, non è molto utile conoscere i valori di registro poiché sono gestiti dal compilatore. In SBCL è possibile definire VOP (Virtual machine OPeration) con codice assembly - vedere http://sbcl-internals.cliki.net/Adding%20VOPs . –
Sto provando a scrivere un programma vulnerabile a un buffer overflow e codice per sfruttarlo sovrascrivendo l'indirizzo di ritorno sullo stack. –