none
Byte Order von großen Datenfeldern tauschen und Inline Assembly RRS feed

  • Frage

  • Hallo Forum

    Ich habe bei einer Bildverarbeitungsanwendung das Problem, dass ich ein großes Datenfeld mit float Einträgen bekomme, das leider in High-Byte-First (Big Endian) Notation vorliegt. Ich habe daher eine schöne Schleife geschrieben, die das elementweise umkehrt:

    for (DWORD m=0; m<(m_sensor_x * m_sensor_y); m++) {

        pB = (unsigned char*)&pRawData[m];
        h=pB[3]; pB[3] = pB[0]; pB[0] = pB[3];
        h=pB[2]; pB[2] = pB[1]; pB[1] = pB[2];
    }

    Soweit so gut. Diese Schleife wird nur leider wahnwitzig oft durchlaufen und das Datenfeld ist nicht gerade klein. Ich denke mal, dass hier der Rechenaufwand für den Prozessor schon enorm ist, zumal ich mir nicht vorstellen kann, dass der Compiler meine Absicht erkennt und das irgendwie optimiert.

    Beim Nachschlagen im Codehandbuch des Pentium ist mir dann der geniale Befehl BSWAP in die Hände gefallen und schon ist eine uralte Leidenschaft in mir aufgebrochen und ich habe diesen Codeteil wie folgt abgeändert:

    DWORD register SIZ = m_sensor_x * m_sensor_y;
       __asm {
                push ecx
                push edi
                mov  ecx,SIZ
                mov  edi,pRawData
    LOOP1: mov  eax,[edi]
                bswap eax
                mov  [edi],eax
                add  edi,4
                loop LOOP1
                pop  edi
                pop  ecx
       }

    Ich war eigentlich höchst erstaunt, dass dieses Konstrukt tatsächlich funktioniert.

    Meine Fragen daher:

    * Gibt es eine hoch-performante "saubere" C++/Windows Lösung des Problems (API Funktion ö.ä.)

    * Mit welchen Problemen muss ich bei der Inline Assembly Lösung rechnen? Ist die Funktion überhaupt kompatibel mit dem Microsoft Compiler Code? Sollte ich das EAX Register oder die Flags sicherheitshalber auch am Stack sichern? Darf ich den Stack überhaupt so einfach benutzen? Kann ich immer davon ausgehen, dass alle meine Zeiger und Werte aus dem Host-C-Code auch im Datensegment (z.B.: mov eax, ds:[edi]) liegen?

    Grüße

    FireHeart

     

     

     

    Freitag, 27. Mai 2011 09:26

Alle Antworten

  • schaust du hier http://msdn.microsoft.com/en-us/library/4ks26t93%28v=VS.100%29.aspx da steht vieles nötige über inlin assembler drinn.


    Freitag, 27. Mai 2011 10:42
  • 1. IMHO wird inline assmebler für 64bit Projekte nicht unterstützt.
    2. Erscheint mir Dein C++ Code falsch. Müsste lauten:

     h=pB[3]; pB[3] = pB[0]; pB[0] = h;
     h=pB[2]; pB[2] = pB[1]; pB[1] = h;

    3. Vielleicht wird es schneller wenn man eine arithmetische Aufgabe daraus macht:

    DWORD dwData = pRawData[m];
    pRawData[m] = (dwData>>24) |
          ((dwData>>16) & 0x0000ff00) |
          ((dwData<<16) & 0x00ff0000) |
          (dwData<<24);
    pRawData[m] = dwData;

    Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de
    Samstag, 28. Mai 2011 08:06
    Moderator
  • Du kannst von C++-Text direkt auf die bswap-Anweisung zugreifen, indem du das _byteswap_ulong()-Intrinsic nutzt:

     

    *blubb = _byteswap_ulong(file.nextInt());
    

     

    kompiliert zu

     

    011F5A40 mov  eax,dword ptr [esp+10h] 
    011F5A44 bswap eax 
    011F5A46 mov  dword ptr [esi],eax 

     

    Gruß, Ky

     

     



    Samstag, 28. Mai 2011 16:50