Illegal instruction in ASM: lock cmpxchg dest, src
Ich ve wurde Herumspielen mit einigen x86 assembly, wie Ihr in vielen meiner Klassen. Insbesondere wollte ich aussetzen, compare-and-swap (CAS) als Benutzer-Funktion. Dies ist mit der Absicht, dass ich es umsetzen kann meine eigenen Schlösser.
Ich bin mit Linux 2.6.31 mit GCC 4.1.1 auf eine Intel CPU.
Habe ich Folgendes:
//int cmpxchg(int *dest, int expected, int update)
.globl cmpxchg
cmpxchg:
pushl %ebp
movl %esp, %ebp
//edx holds dest
movl 8(%ebp), %edx
//eax holds expected value
movl 12(%ebp), %eax
//ecx holds the new value
movl 16(%ebp), %ecx
//cmpxchg dest_addr, exp_value
//compare to %eax is implicit
lock cmpxchgl %edx, %ecx
leave
ret
Dies ist innerhalb einer *.s-Datei, die ich kompilieren mit meiner Treiber-Programm. Wenn ich die Zeile
lock cmpxchgl %edx, %ecx
und auszuführen, erhalte ich eine "Illegal instruction" Fehler.
Wenn ich ersetzen Sie die Zeile mit
cmpxchgl %edx, %ecx
mein code scheint zu verlaufen.
First off, ist lock
notwendig? Ich bin mir nicht sicher, ob cmpxchgl
ist natürlich die Atom -, so habe ich lock
um sicher zu sein. Als userland-Programm, bin ich auch nutzen darf lock
?
Dank
================================================================
Mein letzten code (für diejenigen, die Wandern hier in der Zukunft):
//int cmpxchg(int *dest, int expected, int update)
.globl cmpxchg
cmpxchg:
pushl %ebp
movl %esp, %ebp
//edx holds dest, use eDx for Destination ;-)
movl 8(%ebp), %edx
//eax holds expected value implicitly
movl 12(%ebp), %eax
//cmpxchg dest_add, src_value
lock cmpxchgl %edx, 16(%ebp)
leave
ret
- Warum verwenden Sie nicht nur ein futex ? (en.wikipedia.org/wiki/Futex) Mit nur 6 Stunden Montage, Sie können nicht garantieren, dass dieser code funktioniert ohne Probleme auf jedem Prozessor gibt. Siehe timetobleed.com/mysql-doesnt-always-suck-this-time-its-amd
- Vielleicht versucht er nur, um zu lernen. Das Rad neu erfinden ist schlecht für Produktion code, aber ein ausgezeichneter Weg, um besser auf die Codierung.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Müssen Sie
cmpxchgl %edx, (%ecx)
Diese operation macht keinen Sinn, es sei denn, das Ziel ist ein Speicher-operand, aber die Anleitung ermöglicht ein registrieren Ziel. Die CPU Schuld ist, wenn in der Anweisung verwendet ein register Modus.
Versuchte ich es, Ihr code funktioniert mit einem Speicher-Operanden. Ich weiß nicht, ob Ihnen das bewusst ist, aber diese Sequenz (mit einem register als Ziel) hat einen populären Namen: "die f00fc7c8 bug" oder "die: F00F-bug". Im Pentium Tagen wurde ein "HCF" (halt und Feuer fangen) oder "killer-poke" - Befehl, als wäre es eine Ausnahme generieren, wäre es dann nicht bedienen können, denn der bus war verschlossen, und es war aufrufbar aus user-Modus. Ich denke, es könnte sich um ein OS-level-software-workaround.
(%ecx)
oderoffset(%ecx)
.CMPXCHG8B
Anleitung, die ist nicht die gleiche wie dieCMPXCHG
Anweisung die OP ist mit.F00F
.Ross die Antwort schon sagt, die meisten diese, aber ich werde es versuchen und klären ein paar Dinge.
LOCK
Präfix ist erforderlich, wenn Sie möchten, Unteilbarkeit. Die einzige Ausnahme ist dieXCHG
(nichtCMPXCHG
) Anleitung, die ist standardmäßig gesperrt, so asveikau hingewiesen.LOCK
von user-mode-code.CMPXCHG
mit einem register destination-Operanden.Das heißt, es ist nicht legal zu verwenden, eine
LOCK CMPXCHG
zusammen mit einem register destination-Operanden. Zitieren volume 2A die IA-32-Anleitung (Seite 3-538 in meiner Kopie):Ihr Programm kompiliert wird hier fein (GNU als 2.20) (ich klebte es in die Testphase.s und lief as-a-test.a-test.s)
Als für die Sperre, intel-Dokumentation sagt:
Neugierig, ist das der endgültige code immer noch korrekt? Von was ich sehen kann, du machst den Vergleich in umgekehrter, ist, dass Sie vergleichen den Wert des Zeigers (d.h., die tatsächliche Adresse, auf die Zeiger beziehen) mit der Ganzzahl verwendet wird, wie das update ... außerdem das Ziel gesetzt ist, als die temporäre int verwendet wird, wie das update Wert. In anderen Worten, anstatt:
Ich würde denken, Sie würde wollen, dass so etwas wie:
Habe den original code tatsächlich wie geplant funktionieren (nicht nur kompilieren), und wenn nicht, hat man am Ende erneut die Organisation des Codes, so dass es sieht eher aus wie der oben?
Dies scheint unwahrscheinlich, dass die Quelle das problem, sondern die offizielle Dokumentation auch fest, dass die Anweisung wird nicht unterstützt, die früher als der 486-Architektur. Ist das auftreten im real-Modus mit dem geschützten Modus überschreibt?