Was ist der Unterschied zwischen or eax,eax
und test eax,eax
? Ich habe gesehen, dass verschiedene Compiler beide für den gleichen Vergleich produzieren und soweit die Dokumentation geht, machen sie genau das Gleiche, also frage ich mich, warum sie nicht alle test eax,eax
verwenden. Wenn man darüber nachdenkt, würde and eax,eax
die Flags auf identische Weise setzen, aber ich habe es weder in Freepascal, Delphi noch in msVC ++ gesehen.
Ich habe einige asm-Blöcke in Delphi kompiliert und die Assembler-Quelle ausgecheckt und alle drei Formen haben die gleiche Länge in Opcodes und haben auch die Intel-Performance-PDF überprüft und sie haben die gleiche Latenz und den gleichen Durchsatz.
Bearbeiten:
Die Frage betrifft insbesondere den Unterschied zwischen den spezifischen Fällen test eax,eax
, or eax,eax
und and eax,eax
. Alle 3 ergeben völlig identische Ergebnisse für Register, Flags, Opcode-Länge, Latenz, Durchsatz. Und doch, wenn 0, wenn nicht Null, oder wenn signiert, einige Compiler test eax,eax
verwenden, während einige or eax,eax
verwenden, und ich frage mich, warum sie nicht alle test eax,eax
verwenden, da es den Code sehr leicht macht klarer.
Bearbeiten2:
Als Referenz bin ich zu Hause und habe nur msvc ++ und Delphi hier und älter, aber testet eine Variable wenn Null, msvc ++ tut test eax,eax
, während Delphi or eax,eax
macht.
Im Allgemeinen besteht der einzige Unterschied zwischen test
und and
darin, dass test <reg>, <reg>
seine Operanden nicht ändert. Im Wesentlichen wendet test
eine Operation and
an und verwirft den Nicht-Flag-Teil des Ergebnisses. Wenn die Operanden identisch sind, sind die Ergebnisse gleich (wie auch or
).
test
kann aufgrund von Dingen wie Mikro-Op-Fusion eine überlegene Befehlswahl sein. Daher wird test
normalerweise bevorzugt, es sei denn, die Berechnung müsste wiederholt werden. Dasselbe gilt für cmp
/ sub
.
Durchsuchen Sie Intels Dokument für "Fusion" und Sie sollten die Details finden.
Um nur ein wenig zu wiederholen und etwas hinzuzufügen, was @gsg angezeigt hat, führt die TEST-Anweisung einen bitweisen logischen Vergleich (im wesentlichen bitweise AND-Verknüpfung, aber nicht Speichern des Ergebnisses) von zwei Operanden durch und setzt die Prozessorflags entsprechend zu dem Ergebnis dieser Operation. Der ODER-Befehl führt ein logisches ODER der Quelle mit dem Ziel durch, speichert das Ergebnis im Ziel und setzt die Prozessorflags entsprechend dem Ergebnis. Beide beeinflussen die Prozessor-Flags auf die gleiche Weise. Wenn also die Operanden identisch sind, ist das Verhalten dasselbe. Flags unterscheiden sich nicht. Wenn die Operanden jedoch unterschiedlich sind, ist ihr Verhalten dann ganz anders. Sie können auch mit and eax,eax
auf Null testen, was sich auch auf die Flags auswirkt.
Die Schaltung zur Bestimmung, dass der Inhalt von eax
nach test eax, eax
derselbe ist wie vor der Anweisung, ist einfacher als die Schaltung, die erforderlich ist, um zu dieser Schlussfolgerung für or eax, eax
zu gelangen. Aus diesem Grund ist test
besser.
Einige Compiler haben möglicherweise or
zu einem Zeitpunkt erzeugt, als es keinen Unterschied machte (vor der Ausführung außerhalb der Reihenfolge), aber es wird heutzutage bei einigen Prozessoren außerhalb der Reihenfolge einen Unterschied machen (während noch andere OOO-Prozessoren werden so ausgefeilt sein, dass sie or eax, eax
als wirklich äquivalent zu test eax, eax
) erkennen werden.
Ich konnte keine Referenz finden, die rechtfertigt, dass einige moderne Prozessoren tatsächlich daraus schließen können, dass or reg, reg
reg
nicht modifiziert, aber hier ist eine Antwort, die behauptet, dies sei der Fall für xchg reg, reg
.
Tags und Links assembly x86 micro-optimization