Mit Inline-Assembler [gcc, intel, c], prüfen, ob das Übertrags-Flag nach einer Operation gesetzt ist?Prüfen, ob Übertragsmerker gesetzt ist
Antwort
Mit bedingten Sprüngen jc
(springen wenn tragen) oder jnc
(springen, wenn nicht tragen).
Oder Sie können den Carry-Flag speichern,
;; Intel syntax
mov eax, 0
adc eax, 0 ; add with carry
ah ok, kannte die jc, jnc, adc Befehle nicht. Thx – hans
Warnin, GCC verwendet AT & T-Syntax. Das ist Intel Syntax ... –
@Fififox, danke. Ich habe meine Antwort bearbeitet. –
sbb %eax,%eax
speichert -1 in EAX, wenn der Carry-Flag gesetzt ist, 0, wenn es klar ist. Es ist nicht notwendig, eax auf 0 zu setzen; das Subtrahieren von eax von sich selbst tut das für dich. Diese Technik kann sehr leistungsfähig sein, da Sie das Ergebnis als Bitmaske verwenden können, um die Ergebnisse von Berechnungen zu ändern, anstatt bedingte Sprünge zu verwenden.
Sie sollten beachten, dass es nur gültig ist, das Übertrags-Flag zu testen, wenn es durch arithmetische Berechnungen INSIDE des Inline-Asm-Blocks gesetzt wurde. Sie können den Übertrag einer Berechnung, die in C-Code ausgeführt wurde, nicht testen, da es verschiedene Möglichkeiten gibt, wie der Compiler Dinge optimieren oder neu anordnen kann, die das Übertrags-Flag überlagern würden.
Allerdings der x86 Assembler hes gewidmet schnell ALU Flag Test Anweisungen namens SETcc, wo die CC ist ALU Flag gewünscht. So können Sie schreiben:
setc AL //will set AL register to 1 or clear to 0 depend on carry flag
or
setc byte ptr [edx] //will set memory byte on location edx depend on carry flag
or even
setc byte ptr [CarryFlagTestByte] //will set memory variable on location CarryFlagTestByte depend on carry flag
Mit SETcc Anweisung Sie Flags wie carry testen können, Null, Zeichen, Überlauf oder Parität, einige SETcc Anweisungen erlauben sofort zwei Flags zu testen.
EDIT: Hinzugefügt einfacher Test in Delphi zum Verschwinden gebracht Zweifel an Begriff schnell
procedure TfrmTest.ButtonTestClick(Sender: TObject);
function GetCPUTimeStamp: int64;
asm
rdtsc
end;
var
ii, i: int64;
begin
i := GetCPUTimeStamp;
asm
mov ecx, 1000000
@repeat:
mov al, 0
adc al, 0
mov al, 0
adc al, 0
mov al, 0
adc al, 0
mov al, 0
adc al, 0
loop @repeat
end;
i := GetCPUTimeStamp - i;
ii := GetCPUTimeStamp;
asm
mov ecx, 1000000
@repeat:
setc al
setc al
setc al
setc al
loop @repeat
end;
ii := GetCPUTimeStamp - ii;
caption := IntToStr(i) + ' ' + IntToStr(ii));
end;
Die Schleife (1M Iterationen) weicht mit Anweisung SETC mehr als 5-mal schneller als Schleife mit adc Instruuction.
BEARBEITEN: Zusätzlicher zweiter Test, welches Testergebnis im Register AL kumulativ im Register CL gespeichert wurde, um realistischer zu sein.
procedure TfrmTestOtlContainers.Button1Click(Sender: TObject);
function GetCPUTimeStamp: int64;
asm
rdtsc
end;
var
ii, i: int64;
begin
i := GetCPUTimeStamp;
asm
xor ecx, ecx
mov edx, $AAAAAAAA
shl edx, 1
mov al, 0
adc al, 0
add cl, al
shl edx, 1
mov al, 0
adc al, 0
add cl, al
shl edx, 1
mov al, 0
adc al, 0
add cl, al
shl edx, 1
mov al, 0
adc al, 0
add cl, al
shl edx, 1
mov al, 0
adc al, 0
add cl, al
shl edx, 1
mov al, 0
adc al, 0
add cl, al
shl edx, 1
mov al, 0
adc al, 0
add cl, al
shl edx, 1
mov al, 0
adc al, 0
add cl, al
end;
i := GetCPUTimeStamp - i;
ii := GetCPUTimeStamp;
asm
xor ecx, ecx
mov edx, $AAAAAAAA
shl edx, 1
setc al
add cl, al
shl edx, 1
setc al
add cl, al
shl edx, 1
setc al
add cl, al
shl edx, 1
setc al
add cl, al
shl edx, 1
setc al
add cl, al
shl edx, 1
setc al
add cl, al
shl edx, 1
setc al
add cl, al
shl edx, 1
setc al
add cl, al
end;
ii := GetCPUTimeStamp - ii;
caption := IntToStr(i) + ' ' + IntToStr(ii);
end;
Rutine Teil mit SETcc Anweisung ist noch schneller für etwa 20%.
Haben Sie ein Zitat, um sie schnell anzurufen? Ich habe in den letzten paar Generationen nicht mit den neuesten CPUs Schritt gehalten, aber lange Zeit wurden diese als langsame Legacy-Opcodes betrachtet. –
@R .. Es besteht kein Zweifel: Sie liegen falsch! Überprüfen Sie den oberen Test! –
@R .. Ja die SETcc ist alte Anweisung, aber ist viel schneller als ADC oder mit Cinditional Jumps wie JC oder JNC. –
Die erste Funktion führt eine vorzeichenlose Addition durch und testet dann mit dem Übertrags-Flag (CF) auf Überlauf. Die Volatilen müssen bleiben. Andernfalls wird der Optimierer Anweisungen neu anordnen, was ziemlich genau zu einem falschen Ergebnis führt. Ich habe gesehen, der Optimierer die jnc
in eine jae
(die auch auf CF basiert) zu ändern.
/* Performs r = a + b, returns 1 if the result is safe (no overflow), 0 otherwise */
int add_u32(uint32_t a, uint32_t b, uint32_t* r)
{
volatile int no_carry = 1;
volatile uint32_t result = a + b;
asm volatile
(
"jnc 1f ;"
"movl $0, %[xc] ;"
"1: ;"
: [xc] "=m" (no_carry)
);
if(r)
*r = result;
return no_carry;
}
Die nächste Funktion ist für die signierten Ints. Gleicher Gebrauch von volatilem gilt. Beachten Sie, dass vorzeichenbehaftete Integer-Mathe über OF-Flag über jno
springt. Ich habe gesehen, dass der Optimierer dies in eine jnb
ändert (die ebenfalls auf OF basiert).
Im großen Bild könnten Sie die Funktionen wie folgt verwenden.Im gleichen großen Bild, werden viele Leute ablehnen wahrscheinlich die zusätzliche Arbeit und Ästhetik nicht-Schönheit bis pwn'd durch einen Überlauf/wrap/Unterlauf
int r, a, b;
...
if(!add_i32(a, b, &r))
abort(); // Integer overflow!!!
...
Die Inline-GCC Montag ist in GCC 3.1 und höher zur Verfügung. Siehe Assembler Instructions with C Expression Operands, oder suchen Sie nach 'GCC Extended Assembly'.
Schließlich wäre das gleiche in Visual Studio wie folgt (nicht viel Unterschied in der Code-Generierung), aber Syntax ist viel einfacher, da MASM Sie zu einem C-Label springen:
/* Performs r = a + b, returns 1 if the result is safe (no overflow), 0 otherwise */
int add_i32(__int32 a, __int32 b, __int32* r)
{
volatile int no_overflow = 1;
volatile __int32 result = a + b;
__asm
{
jno NO_OVERFLOW;
mov no_overflow, 0;
NO_OVERFLOW:
}
if(r)
*r = result;
return no_overflow;
}
Auf dem schlechten Der obige MASM-Code gilt nur für die x86-Assembly. Für x64 Assembly gibt es keine Inlining, so dass Sie es in Assembly (in einer separaten Datei) codieren müssen und verwenden Sie MASM64 zum Kompilieren.
Sie können die Erweiterung goto verwenden, um zu einer C-Marke zu springen, indem Sie z. asm flüchtige goto ("ja% l [cabel]"::: "speicher": cabel) ;, wo cabel ist C label –
Lesen unter der Antwort von @R .. scheint Ihre Funktion ungültig zu machen. 'Sie sollten sich darüber im Klaren sein, dass es nur gültig ist, das Übertrags-Flag zu testen, wenn es durch arithmetische Berechnungen innerhalb des Inline-Asm-Blocks gesetzt wurde. Sind Sie sich dessen sicher? –
@DrBeco - ja, für GCC, es kommt darauf an. GCC stellt die "Folgerichtigkeit" der Anweisungen in Ihrem Block sicher, aber es kann seine eigenen Anweisungen einfügen/verschachteln. Wenn GCC-Anweisungen CC nicht ändern, ist alles in Ordnung. Der Inline-Assembler von Microsoft unterliegt nicht den Einschränkungen von GCC. – jww
- 1. Prüfen, ob Variablen gesetzt sind
- 2. Prüfen, ob ein BOOL gesetzt ist (nicht möglich mit == nil)
- 3. Prüfen, ob php get Variable auf irgendwas gesetzt ist?
- 4. Prüfen, ob ein Bit gesetzt ist oder nicht
- 5. überprüfen, ob Umgebungsvariable bereits gesetzt ist
- 6. Prüfen, ob DB verfügbar ist
- 7. Prüfen, ob PyObject ist Keine
- 8. Prüfen, ob Service verfügbar ist
- 9. Prüfen, ob ein Objekt ist
- 10. Prüfen, ob Boolean wahr ist?
- 11. Wie überprüfen, ob Objektvariable gesetzt ist
- 12. Überprüfen, ob Sitzungsschlüssel in Django gesetzt ist
- 13. VBA prüfen, ob die Variable ist leer
- 14. prüfen, ob eine Eigenschaft gesetzt wurde - mit Moq
- 15. Was ist der beste Weg zu prüfen, ob ein Attribut existiert und gesetzt ist?
- 16. javascript prüfen, ob Array-Schlüssel
- 17. Prüfen, ob Adobe Reader installiert ist (C#)?
- 18. Ruhezustand: prüfen, ob Objekt vorhanden ist
- 19. PostgreSQL-Funktion prüfen, ob Feld CSV ist
- 20. Prüfen, ob div ID vorhanden ist (PHP)
- 21. Prüfen, ob eine Variable definiert ist?
- 22. Prüfen, ob Sympy Expression Nan ist?
- 23. Linq2SQL zu prüfen, ob Artikel null ist
- 24. C# prüfen, ob ein Dateiziel gültig ist
- 25. win32: prüfen, ob das Fenster minimiert ist
- 26. Prüfen, ob Knoten in h5py vorhanden ist
- 27. Prüfen, ob Textansicht in Android ellipsentiert ist
- 28. Prüfen, ob das Anrufergebnis nicht definiert ist
- 29. Kompilierzeit prüfen, ob eine Basisklasse "interface" ist
- 30. Prüfen, ob der Datepicker geöffnet ist
Sie möchten dies innerhalb eines asm-Blocks testen oder den Zustand des carry-Flags an etwas im C-Code übergeben, in dem Ihre ASM inline ist? –
Testen in einem Block von Asm ist ausreichend. es auszugeben sollte nicht so schwer sein. – hans