Wie zu lesen und x86 Fahnen schreiben direkt Register?
Frage
Von dem, was ich gelesen habe, scheint, wie gibt es 9 verschiedene Flaggen. Ist es möglich, sie direkt zu lesen / verändern? Ich weiß, ich kann zum Beispiel wissen, ob der Null-Flag nachdem ich einen cmp / JMP-Befehl gesetzt ist, aber ich frage, ob es möglich ist so etwas wie
zu tunmov eax, flags
oder so etwas.
Auch für das Schreiben, ist es möglich, sie von Hand zu setzen?
Lösung
können Einige Flaggen direkt mit spezifischen Anweisungen gesetzt oder gelöscht werden:
- CLC , STC und CMC : klar, gesetzt, und den Carry-Flag ergänzen
- CLI und STI : klar und stellen Sie den Interrupt-Flag (das atomar getan werden soll)
- CLD und STD : klar und stellen Sie die Richtungs-Flag
Für das Lesen und Schreiben der Zeichen, Null, Hilfs carry, Parität und tragen Fahnen, können Sie LAHF die unteren 8 Bits laden (diese 5 Flaggen plus 3 unbestimmte Bits) in das AH-Register, und Sie können mit SAHF die Werte von AH speichern zurück in die Flag-Register.
Sie können auch die PUSHF Anweisung die Fahnen auf den Stapel zu drücken, so dass sie auf dem Stapel lesen und ändern, und dann den POPF 1 Anweisung sie die Fahnen zurück zu speichern, in registrieren.
Beachten Sie, dass Sie nicht die VM und RF-Flags mit POPF einstellen können - sie ihre vorherigen Werte behalten. In ähnliche Weise können Sie nur die E / A-Berechtigungsebene ändern, wenn auf Berechtigungsstufe 0 und der Interrupt-Flag Ausführung kann nur geändert werden, wenn sie bei einer Berechtigungsstufe mindestens so privilegiert ist wie die I / O-Privilegebene ausgeführt wird.
Fußnote 1:
Beachten Sie, dass popf
auf modernen CPUs recht langsam ist; finden Sie unter Agner Fog Optimierung Führung und Anleitung Tabellen. Es ist mikrocodiert, weil im Kernel-Modus es in der Lage ist IF und AC und IO Berechtigungsebene zu ändern. Wir leiden die Strafe unabhängig von Modus auf aktuellen CPUs, da die Decoder nicht moden empfindlich sind.
Wenn möglich, verwenden lahf / SAHF statt PUSHF / POPF für die Leistung oder eine einzelne Flagge speichern Sie wie setc al
kümmern dann später add al, 255
CF = (AL!=0)
einzustellen. Oder setnc al
/ sub al, 1
oder was auch immer. Sequenzen zu setzen oder zu löschen SF oder OF basierend auf ein 0 oder 1 Register sind auch einfach, mit / ohne die Flagge zu invertieren.
Andere Tipps
Sie können die PUSHF und POPF Anweisungen verwendet werden, die die Fahnen auf den Stapel schieben wird, können Sie sie ändern können, und sie dann aus Pop zurück.
Wenn Sie nur das untere Byte der Flags müssen registrieren (enthält SF, ZF, AF, PF, CF), dann gibt es die seltsame, aber bequeme Anweisung LAHF (ha ha), die die unteren 8 Bits der Lasten flags in AH registrieren, und sein Gegenstück in SAHF AH-Flags zu speichern.
Für den Carry-Flag speziell, x86 CLC, STC und CMC bietet, zu löschen, setzen, und den Carry-Flag ergänzen ist.
einfachste Weg ist, mit PUSHF / POPF .
Wenn Sie eflags
in eax
verschieben möchten, verwenden Sie folgenden Code.
pushf # push eflags into stack
pop %eax # pop it into %eax
SETcc
Diese Anweisung Familie ist ein weiterer Weg, um einige Fahnen / Kombination von Fahnen zu beobachten.
Es setzt den Wert eines Bytes auf der Grundlage der einzelnen FLAGS.
Z. B, für CF
:.
stc
setc al
; al == 1
clc
setc al
; al == 0
Runnable GitHub stromaufwärts mit Behauptungen .
Jcc
Diese Anweisung Familie natürlich ist eine weitere Möglichkeit für bestimmte Flags und könnte verwendet werden, SETcc
zu implementieren:
jc set
mov al, 0
jmp end
set:
mov al, 1
end:
- LAHF: Lasten Statusflags in AH
- Kopiert der Low-Byte der EFLAGS-Register einschließlich Zeichen, Zero, und Fahnen tragen.
-
Speichern Sie eine Kopie des Flags in einer Variablen zur Aufbewahrung
.data saveflags BYTE ? .code lahf ; load flags into AH mov saveflags,ah ; save them into a variable
-
SAHF: speichert AH in Statusflags
- Kopien AH in den Low-Byte der EFLAGS-Register
-
Rufen Sie den Wert der Flags früher gespeichert
.code mov ah, saveflags ; load save flags into AH sahf ; copy into flags register