Frage

Ich kopiere Elemente von einem Array zum anderen in C ++. ich fand die rep movs Anweisung in x86, die ein Array bei ESI zu einem Array bei EDI von Size ECX kopiert. Allerdings weder die for Noch while Schleifen, die ich versucht habe, zu einem zusammengestellt zu werden rep movs Anweisung in VS 2008 (auf einem Intel Xeon X64 -Prozessor). Wie kann ich Code schreiben, der zu dieser Anweisung zusammengestellt wird?

War es hilfreich?

Lösung

Wenn Sie genau diese Anweisung benötigen, verwenden Sie den integrierten Assembler und schreiben Sie diese Anweisung manuell. Sie können sich nicht auf den Compiler verlassen, um einen bestimmten Maschinencode zu erzeugen - Auch wenn es es in einer Zusammenstellung ausgibt, kann es sich entscheiden, während der nächsten Zusammenstellung ein anderes Äquivalent auszugeben.

Andere Tipps

Ehrlich gesagt sollten Sie nicht. Rep ist eine Art veraltetes Übertrag im Befehlssatz und eigentlich ziemlich langsam, da sie eine mikrokodierte Unterroutine innerhalb der CPU aufrufen muss, die eine ROM -Lokup -Latenz hat und ebenfalls nicht ausgerichtet ist.

In fast jeder Implementierung werden Sie feststellen, dass die memcpy() Compiler Intrinsic ist beide einfacher zu bedienen und läuft schneller.

Unter MSVC gibt es die __movsxxx & __stosxxx Intrinsik, die a erzeugen werden REP vorangestellte Anweisung.

Es gibt auch einen "Hack", um intrinsisch zu erzwingen memset AKA REP STOS Nach VC9+, da das Intrinsische aufgrund der SSE2 -Verzweigung in der CRT nicht mehr verlässt. Das ist besser als __stosxxx Aufgrund der Tatsache kann der Compiler es für Konstanten optimieren und korrekt bestellen.

#define memset(mem,fill,size) memset((DWORD*)mem,((fill) << 24|(fill) << 16|(fill) << 8|(fill)),size)
__forceinline void memset(DWORD* pStart, unsigned long dwFill, size_t nSize)
{
    //credits to Nepharius for finding this
    DWORD* pLast = pStart + (nSize >> 2);
    while(pStart < pLast)
        *pStart++ = dwFill;

    if((nSize &= 3) == 0)
        return;

    if(nSize == 3)
    {
        (((WORD*)pStart))[0]   = WORD(dwFill);
        (((BYTE*)pStart))[2]   = BYTE(dwFill);
    }
    else if(nSize == 2)
        (((WORD*)pStart))[0]   = WORD(dwFill);
    else
        (((BYTE*)pStart))[0]   = BYTE(dwFill);
}

Natürlich REP Ist nicht immer das Beste, was man verwenden kann, wenn Sie sich besser verwenden, wenn Sie sich besser verwenden memcpy, es wird entweder auf SSE2 oder auf SSE2 verzweigen REPS MOV Basierend auf Ihrem System (unter MSVC), es sei denn, Sie möchten eine benutzerdefinierte Montage für "heiße" Bereiche schreiben ...

Repräsentant und Freunde waren einmal nett, als die X86-CPU ein industrieller KISC-Prozessor mit einer Pipeline war.

Aber das hat sich geändert. Heutzutage, wenn der Prozessor begegnet irgendein Anweisungen, das erste, das es tut, besteht Kann verwendet werden, um die Schreib- nach dem Schreiben von Sequenzen in Einzelgeschnitten zu vereinfachen, etc.). Diese Maschinerie eignet sich gut für Anweisungen, die sich in einigen VLIW-ähnlichen Opcodes übersetzt, aber nicht in Maschinencode, die in Schlaufen übersetzt werden. Schleifenüberletzter Maschinencode führt wahrscheinlich dazu, dass die Ausführungspipeline zum Stillstand kommt.

Anstatt Hunderttausende von Transistoren für den Bau von CPU-Zirkuitrie zum Umgang mit Schleifen von Teilen der Mikroopien in der Ausführungspipeline auszugeben Schreiben Sie Ihre eigenen verdammten Loops!

Daher wird es selten verwendet, wenn Maschinen Code schreiben. Wenn Sie in einer binären ausführbaren Datei auftreten, ist es wahrscheinlich eine menschliche Versammlung, die es nicht besser kannte, oder ein Cracker, der die wenigen Bytes, die es für die Verwendung von es anstelle einer tatsächlichen Schleife, wirklich brauchte, die sie geschrieben hat.

(Nehmen Sie jedoch alles, was ich gerade mit einem Körnchen Salz geschrieben habe. Vielleicht stimmt das nicht mehr. Ich bin nicht mehr 100% auf dem neuesten

Ich verwende die Rep* Prefix -Varianten mit CMPS*, MOVS*, SCAs* und STOS* Anweisungsvarianten, um Inline -Code zu generieren, der die Codegröße minimiert, unnötige Anrufe/Sprünge vermeidet und dadurch die von den Caches erledigten Arbeiten unterhält. Die Alternative besteht darin, Parameter einzurichten und ein Memset oder ein Memcpy an einem anderen Ort aufzurufen, was insgesamt schneller sein kann, wenn ich hundert Bytes oder mehr kopieren möchte, aber wenn es nur eine Frage von 10 bis 20 Bytes mit Rep ist, ist es schneller (oder zumindest Das letzte Mal habe ich gemessen).

Da mein Compiler die Spezifikation und Verwendung von Inline -Montagefunktionen ermöglicht und deren Registerverbrauch/-änderung in den Optimierungsaktivitäten enthält, kann ich sie verwenden, wenn die Umstände stimmen.

In historischer Hinweis - keinen Einblick in die Strategien des Herstellers - gab es eine Zeit, in der die Anweisungen "Rep Movs*" (etc) sehr langsam waren. Ich denke, es war ungefähr die Zeit des Pentium/Pentium -MMX. Ein Kollege von mir (der mehr Einblicke hatte als ich) sagte, dass die Hersteller den Chipbereich verringert hatten (<=> weniger Transistoren/mehr Mikrocode), die der Rep -Handhabung zugewiesen wurden, und es benutzte, um andere, verwendete Anweisungen schneller zu machen.

In den fünfzehn Jahren, da Rep wieder relativ schneller geworden ist, würde dies mehr Transistoren/weniger Mikrocode vermuten lassen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top