Was bedeutet „rep; nein; " Mittelwert in x86-Assembly? Ist es dasselbe wie die Anweisung "Pause"?

83
  • Was heißt rep; nopdas
  • Ist es dasselbe wie pauseAnweisung?
  • Ist es dasselbe wie rep nop(ohne das Semikolon)?
  • Was ist der Unterschied zu der einfachen nopAnweisung?
  • Verhält es sich auf AMD- und Intel-Prozessoren anders?
  • (Bonus) Wo ist die offizielle Dokumentation für diese Anweisungen?

Motivation für diese Frage

Nach einigen Diskussionen in den Kommentaren einer anderen Frage wurde mir klar, dass ich nicht weiß, was rep; nop;in x86- (oder x86-64-) Assembly bedeutet. Außerdem konnte ich im Web keine gute Erklärung finden.

Ich weiß, dass dies repein Präfix ist, das "die nächsten Befehlszeiten wiederholen cx" bedeutet (oder zumindest in einer alten 16-Bit-x86-Assembly). Nach dieser Übersichtstabelle auf Wikipedia , scheint es repnur mit verwendet werden movs, stos, cmps, lods, scas(aber vielleicht diese Begrenzung auf neueren Prozessoren entfernt wurde). Daher würde ich denken rep nop(ohne Semikolon) würde eine nopOperation cxmal wiederholen .

Nach weiterer Suche wurde ich jedoch noch verwirrter. Es scheint, dass rep; nopund pause Karte auf genau den gleichen Opcode und pausehat ein etwas anderes Verhalten als nur nop. Einige alte Mails aus dem Jahr 2005 sagten verschiedene Dinge:

  • "Versuche nicht zu viel Strom zu verbrennen"
  • "Es ist gleichbedeutend mit 'nop', nur mit 2-Byte-Codierung."
  • "Es ist Magie auf Intel. Es ist wie 'Nein, aber lassen Sie die anderen HT-Geschwister laufen'"
  • "Es ist eine Pause für Informationen und eine schnelle Polsterung für Athlon."

Mit diesen unterschiedlichen Meinungen konnte ich die richtige Bedeutung nicht verstehen.

Es wird im Linux-Kernel (sowohl auf i386 als auch auf x86_64 ) zusammen mit diesem Kommentar verwendet: /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */Es wird auch in BeRTOS mit demselben Kommentar verwendet.

Denilson Sá Maia
quelle
2
Siehe auch
jfritz42

Antworten:

73

rep; nopist in der Tat das gleiche wie die pauseAnweisung (Opcode F390). Es kann für Assembler verwendet werden, die die pauseAnweisung noch nicht unterstützen . Auf früheren Prozessoren hat dies einfach nichts bewirkt, genau wie nopin zwei Bytes. Auf neuen Prozessoren, die Hyperthreading unterstützen, wird dies als Hinweis für den Prozessor verwendet, dass Sie einen Spinloop ausführen, um die Leistung zu steigern. Aus Intels Anweisungsreferenz :

Verbessert die Leistung von Spin-Wait-Schleifen. Beim Ausführen einer „Spin-Wait-Schleife“ erleidet ein Pentium 4- oder Intel Xeon-Prozessor beim Verlassen der Schleife einen schwerwiegenden Leistungsverlust, da er eine mögliche Verletzung der Speicherreihenfolge erkennt. Der PAUSE-Befehl gibt dem Prozessor einen Hinweis darauf, dass die Codesequenz eine Spin-Wait-Schleife ist. Der Prozessor verwendet diesen Hinweis, um die Verletzung der Speicherreihenfolge in den meisten Situationen zu vermeiden, wodurch die Prozessorleistung erheblich verbessert wird. Aus diesem Grund wird empfohlen, eine PAUSE-Anweisung in alle Spin-Wait-Schleifen einzufügen.

ughoavgfhw
quelle
4
Ist die Spin-Wait-Schleife dieselbe wie die Busy-Wait-Schleife ? Gilt diese "Verbesserung" nur für Hyperthreading-Prozessoren? (und warum?)
Denilson Sá Maia
11
Ja, die Spin-Wait-Schleife entspricht der Busy-Wait-Schleife. Der Vorteil gilt auch für CPUs, die kein Hyper-Threading unterstützen. Es kann als Begrenzung der Anzahl (unnötiger) Anweisungen in der Pipeline angesehen werden (anstatt zu versuchen, viele Iterationen der Schleife parallel
Brendan
1
@Brendan, danke! Ich habe es überhaupt nicht verstanden, bis Sie die Sache über Iterationen der Schleife parallel gesagt haben.
Prof. Falken
11
@Brendan, Oh, jetzt verstehe ich es! Diese modernen Prozessoren sind superskalar und versuchen daher, mehrere Anweisungen gleichzeitig auszuführen. Wenn es sich um eine Busy-Wait-Schleife handelt, wird das Ausführen weiterer Anweisungen nicht schneller, da nur auf eine andere Bedingung gewartet wird.
Denilson Sá Maia
1
@Denilson: Ja, Hyperthreading-Freundlichkeit (oder nur Energieeinsparung ohne HT) ist ein großer Vorteil, aber der andere vermeidet eine Fehlerspekulation in der Speicherreihenfolge beim Verlassen der Spin-Schleife. Ohne pauseist Ihre Spin-Schleife effektiv eine Pipeline langsamer, um die Zustandsänderung des von einem anderen Kern geschriebenen Speicherorts zu bemerken.
Peter Cordes
13

rep nop= F3 90 = die Codierung für pausesowie die Dekodierung auf älteren CPUs, die dies nicht unterstützen pause.


Präfixe (außer lock), die nicht für eine Anweisung gelten, werden in der Praxis von vorhandenen CPUs ignoriert.

In der Dokumentation heißt es, dass die Verwendung repmit Anweisungen, für die sie nicht gilt, "reserviert ist und unvorhersehbares Verhalten verursachen kann", da zukünftige CPUs sie möglicherweise als Teil einer neuen Anweisung erkennen. Sobald sie eine bestimmte neue Befehlskodierung mit erstellt haben f3 xx, dokumentieren sie, wie sie auf älteren CPUs ausgeführt wird. (Ja, der x86-Opcode-Speicherplatz ist so begrenzt, dass sie solche verrückten Sachen machen, und ja, das macht die Decoder kompliziert.)

In diesem Fall bedeutetpause dies, dass Sie in Spinloops verwenden können, ohne die Abwärtskompatibilität zu beeinträchtigen . Alte CPUs, die nichts davon wissen pause, dekodieren es als NOP, ohne Schaden zuzufügen, wie durch Intels ISA-Referenzhandbuch fürpause garantiert . Bei neuen CPUs profitieren Sie von Energieeinsparung / HT-Freundlichkeit und vermeiden Fehlerspekulationen bei der Speicherreihenfolge , wenn sich der Speicher, auf dem Sie sich drehen, ändert und Sie die Spin-Schleife verlassen.


Links zu Intels Handbüchern und vielen anderen guten Dingen auf der x86-Tag-Wiki-Infoseite

Ein weiterer Fall, in dem ein bedeutungsloses repPräfix zu einer neuen Anweisung für neue CPUs wird: lzcntist F3 0F BD /r. Auf CPUs, die diese Anweisung nicht unterstützen (das LZCNT-Feature-Flag fehlt in ihrer CPUID), wird sie als dekodiert rep bsr, was genauso ausgeführt wird wie bsr. Auf alten CPUs erzeugt es also 32 - expected_resultund ist undefiniert, wenn die Eingabe Null war.

Aber tzcntund bsfdas gleiche tun mit Nicht-Null - Eingänge, so Compiler kann und verwenden , tzcntauch wenn es nicht garantiert ist , dass die Ziel - CPU als ausgeführt wird tzcnt. AMD-CPUs sind schnell tzcnt, langsam bsfund bei Intel sind beide schnell. Solange es für die Korrektheit keine Rolle spielt (Sie verlassen sich nicht auf das Setzen von Flags oder darauf, dass das Zielverhalten im Fall input = 0 unverändert tzcntbleibt ), ist es hilfreich , es wie auf CPUs dekodieren zu lassen, die es unterstützen.


Ein Fall eines bedeutungslosen repPräfixes, das wahrscheinlich nie anders dekodiert wird: Wird rep retstandardmäßig von gcc verwendet, wenn auf "generische" CPUs abgezielt wird (dh keine bestimmte CPU mit -marchoder -mtuneanvisiert wird und AMD K8 oder K10 nicht anvisiert werden). Es wird Jahrzehnte vor irgendjemandem sein könnte eine CPU machen, die rep retals etwas anderes dekodiert als ret, weil sie in den meisten Binärdateien in den meisten Linux-Distributionen vorhanden ist. Siehe Was bedeutet "rep ret"?

Peter Cordes
quelle
3
Das repPräfix wurde auch von Intel verwendet, um die Sperrentfernung hinzuzufügen.
Paul A. Clayton
Präfixe, die nicht für eine Anweisung gelten, werden ignoriert. Es wird jedoch erwähnt, dass Wiederholungspräfixe ( F2Hund F3H) reserviert sind und zu unvorhersehbarem Verhalten in Tabelle 11-3 führen können. Auswirkung von Präfixen auf SSE-, SSE2- und SSE3-Anweisungen . Daher wird die Präfixanwendung für einige Anweisungen ignoriert, nicht für alle. Wird diese Funktion als undokumentiert betrachtet?
St.Antario
2
@ St.Antario: Sie formulieren es so, weil zukünftige CPUs es als Teil einer neuen Anweisung erkennen könnten. Auf allen realen CPUs war dies der Fall, und sobald sie eine Codierung mithilfe erstellt haben f3 xx, dokumentieren sie, wie sie auf älteren CPUs ausgeführt wird.
Peter Cordes
1
Präfixe (außer Sperren), die nicht für eine Anweisung gelten, werden in der Praxis von vorhandenen CPUs ignoriert. Es ist dokumentiert, dass rep movbeUrsachen #UD, so repwird nicht immer ignoriert. Auch wenn es nicht für eine Anweisung in dem Sinne gilt, wie es im REP/REPE/REPZ/REPNE/REPNZmanuellen Eintrag angegeben ist.
St.Antario
2
@ St.Antario: Interessant! Im Allgemeinen werden bei älteren Anweisungen nicht zutreffende Präfixe ignoriert. Wenn Sie eine neue Anweisung einführen, können Sie bei Bedarf strengere Regeln hinzufügen. IDK, warum sie das für diesen speziellen Fall wählen würden.
Peter Cordes