Inline-Assembler Maximum eines Arrays



  • Hi:

    Ich möchte mit folgender Funktion das Maximum eines Feldes ermitteln (In der Hoffnung dass es schnell ist, wer weiß vielleicht bringt ja ein in C implementierter Heapsort mehr...). Kann mir jemand sagen, wo der Fehler liegt.
    Nach START wird die Adresse in EAX immer 9 und das ist ja geschützter Speicher und es erscheint ein Zugriffsfehler.

    Danke im Vorraus....

    DSidious

    int MaxInArray(int *feld, int anzahl)
    {
      int max;
    
      _asm
      {
        push esi
        push edi
    
        xor  esi, esi
        xor  edi, edi
    
        // Startwert
        mov eax, [feld] 
        mov ebx, [eax]
    
        START:
    
          // Zahl einlesen und vergleichen
          mov eax, [feld+edi]
          mov ecx, [eax]
          cmp ebx, ecx
    
          jg ZAHL_GROESSER
          jmp NICHT_TAUSCHEN
    
          ZAHL_GROESSER:
            mov eax, [feld+edi] 
            mov ebx, [eax]
    
          NICHT_TAUSCHEN:
            add edi, TYPE feld
            inc esi
            cmp esi, dword ptr [anzahl]
            jne START
    
          mov dword ptr [max], ebx
    
          pop esi
          pop edi
    
      }
    
      return max;
    }
    


  • Ist dir schonmal aufgefallen, dass edi beim ersten START leer ist?



  • Mhh, doch, was heißt Leer. Es ist 0 und dass soll es ja auch sein. feld+0 ist das erste Element, oder???

    DSidioud



  • Hmmm, ok. Denkfehler meinerseits. 😉



  • mov eax, [feld+edi] 
    mov ecx, [eax]
    

    Damit liest du zuerst den edi-ten Eintrag des Arrays ein und verwendest den danach als Adresse. Dann ists kein wunder 🙂 Versuch mal sowas wie

    lea eax, [feld+edi]
    mov ecx, [eax]
    

    oder gleich

    mov ecx, [feld+edi]
    

    Dasselbe gilt natürlich für:

    // Startwert 
    mov eax, [feld]  
    mov ebx, [eax]
    


  • Oh, ja load effective address; hatte ich wohl vergessen, dass das so ging. Werds gleich mal ausprobieren.

    DSidious



  • wenn du wirklich performance raushollen möchtest, solltest du vielleicht versuchen die jumps zu vermeiden z.B. mit dem cmov. Ansonsten verlierst du auf nem p4 20 takte bei einem nicht vorhergesehenem jump.

    rapso->greets();



  • rapso schrieb:

    wenn du wirklich performance raushollen möchtest, solltest du vielleicht versuchen die jumps zu vermeiden z.B. mit dem cmov. Ansonsten verlierst du auf nem p4 20 takte bei einem nicht vorhergesehenem jump.

    Damit (cmov) grenzt du AMD K6-2 Besitzer aus.



  • dann soll man das halt emulieren,

    cmp,
    carry auf eax,
    mov mit eax als index aus nem array mit 2 einträgen
    xor von eax mit 1
    mov mit eax als index aus nem array mit 2 einträgen (auf anderes register)

    dann hast du zwei register, eines mit einsen das andere mit nullen.

    die ursprüngliche variable AND mit dem einen wert und die die _eventuell_ reingeschrieben werden soll AND mit dem anderen wert (Aus "anderes register")

    die beiden resultate aufaddieren (einer ist ja sicherlich 0)

    schon haste auch jeden 40386-user befriedigt... 🙂

    auch wenn das viel drecksarbeit ist um den cmov zu emulieren, könnte trotzdem fixer sein... jumps are evil!

    so ungefähr läuft das ja auch auf pixel und vertexshadern!

    rapso->greets();

    ps. ich schreib doch net den source für euch! 😃



  • Danke, alles sehr interessant.
    Bis jetzt hab ich es allerdings noch nicht hinbekommen, dass auch das Ergebnis stimmt. 😞

    DSidious



  • *lol*
    Ich weiß noch, wie ich auf meinem alten Rechner (K6-2) ein Programm zum Laufen kriegen wollte, das ständig wegen cmov abgeschmiert ist.
    ich musste jeden cmov durch einen farjump zum Emulationscode ersetzen. Denn jeder noch so gute Emulationscode hat mindestens ein Byte mehr als cmov.
    Aber das Programm lief nach dieser "Spezialbehandlung".


Anmelden zum Antworten