movmem



  • Weiß jemand was der C-Compiler aus der Anweisung

    movmem(a,b,10);

    macht ? Könnte das vielleicht jemand, der einen Disassembler hat, rausfinden ?



  • Ich weiß nicht ob du das wirklich wissen willst aber nun gut 🙂

    Ich nehme an du redest ovn der Funktion memmove und nicht movemem. Das genaue Verhalten hängt von der Runtime--Library ab, ich hab nur gerade den Source vonner M$-RTL da, viel spaß dabei...übrigens ist die Funktion im Source identisch zu memcpy...aber ich sag dir gelich: ich hab dich gewarnt 🙂

    ifdef MEM_MOVE
            _MEM_     equ <memmove>
    else  ; MEM_MOVE
            _MEM_     equ <memcpy>
    endif  ; MEM_MOVE
    
    %       public  _MEM_
    _MEM_   proc \
            dst:ptr byte, \
            src:ptr byte, \
            count:IWORD
    
                  ; destination pointer
                  ; source pointer
                  ; number of bytes to copy
    
    ;       push    ebp             ;U - save old frame pointer
    ;       mov     ebp, esp        ;V - set new frame pointer
    
            push    edi             ;U - save edi
            push    esi             ;V - save esi
    
            mov     esi,[src]       ;U - esi = source
            mov     ecx,[count]     ;V - ecx = number of bytes to move
    
            mov     edi,[dst]       ;U - edi = dest
    
    ;
    ; Check for overlapping buffers:
    ;       If (dst <= src) Or (dst >= src + Count) Then
    ;               Do normal (Upwards) Copy
    ;       Else
    ;               Do Downwards Copy to avoid propagation
    ;
    
            mov     eax,ecx         ;V - eax = byte count...
    
            mov     edx,ecx         ;U - edx = byte count...
            add     eax,esi         ;V - eax = point past source end
    
            cmp     edi,esi         ;U - dst <= src ?
            jbe     short CopyUp    ;V - yes, copy toward higher addresses
    
            cmp     edi,eax         ;U - dst < (src + count) ?
            jb      CopyDown        ;V - yes, copy toward lower addresses
    
    ;
    ; Copy toward higher addresses.
    ;
    ;
    ; The algorithm for forward moves is to align the destination to a dword
    ; boundary and so we can move dwords with an aligned destination.  This
    ; occurs in 3 steps.
    ;
    ;   - move x = ((4 - Dest & 3) & 3) bytes
    ;   - move y = ((L-x) >> 2) dwords
    ;   - move (L - x - y*4) bytes
    ;
    
    CopyUp:
            test    edi,11b         ;U - destination dword aligned?
            jnz     short CopyLeadUp ;V - if we are not dword aligned already, align
    
            shr     ecx,2           ;U - shift down to dword count
            and     edx,11b         ;V - trailing byte count
    
            cmp     ecx,8           ;U - test if small enough for unwind copy
            jb      short CopyUnwindUp ;V - if so, then jump
    
            rep     movsd           ;N - move all of our dwords
    
            jmp     dword ptr TrailUpVec[edx*4] ;N - process trailing bytes
    
    ;
    ; Code to do optimal memory copies for non-dword-aligned destinations.
    ;
    
    ; The following length check is done for two reasons:
    ;
    ;    1. to ensure that the actual move length is greater than any possiale
    ;       alignment move, and
    ;
    ;    2. to skip the multiple move logic for small moves where it would
    ;       be faster to move the bytes with one instruction.
    ;
    
            align   @WordSize
    CopyLeadUp:
    
            mov     eax,edi         ;U - get destination offset
            mov     edx,11b         ;V - prepare for mask
    
            sub     ecx,4           ;U - check for really short string - sub for adjust
            jb      short ByteCopyUp ;V - branch to just copy bytes
    
            and     eax,11b         ;U - get offset within first dword
            add     ecx,eax         ;V - update size after leading bytes copied
    
            jmp     dword ptr LeadUpVec[eax*4-4] ;N - process leading bytes
    
            align   @WordSize
    ByteCopyUp:
            jmp     dword ptr TrailUpVec[ecx*4+16] ;N - process just bytes
    
            align   @WordSize
    CopyUnwindUp:
            jmp     dword ptr UnwindUpVec[ecx*4] ;N - unwind dword copy
    
            align   @WordSize
    LeadUpVec       dd      LeadUp1, LeadUp2, LeadUp3
    
            align   @WordSize
    LeadUp1:
            and     edx,ecx         ;U - trailing byte count
            mov     al,[esi]        ;V - get first byte from source
    
            mov     [edi],al        ;U - write second byte to destination
            mov     al,[esi+1]      ;V - get second byte from source
    
            mov     [edi+1],al      ;U - write second byte to destination
            mov     al,[esi+2]      ;V - get third byte from source
    
            shr     ecx,2           ;U - shift down to dword count
            mov     [edi+2],al      ;V - write third byte to destination
    
            add     esi,3           ;U - advance source pointer
            add     edi,3           ;V - advance destination pointer
    
            cmp     ecx,8           ;U - test if small enough for unwind copy
            jb      short CopyUnwindUp ;V - if so, then jump
    
            rep     movsd           ;N - move all of our dwords
    
            jmp     dword ptr TrailUpVec[edx*4] ;N - process trailing bytes
    
            align   @WordSize
    LeadUp2:
            and     edx,ecx         ;U - trailing byte count
            mov     al,[esi]        ;V - get first byte from source
    
            mov     [edi],al        ;U - write second byte to destination
            mov     al,[esi+1]      ;V - get second byte from source
    
            shr     ecx,2           ;U - shift down to dword count
            mov     [edi+1],al      ;V - write second byte to destination
    
            add     esi,2           ;U - advance source pointer
            add     edi,2           ;V - advance destination pointer
    
            cmp     ecx,8           ;U - test if small enough for unwind copy
            jb      short CopyUnwindUp ;V - if so, then jump
    
            rep     movsd           ;N - move all of our dwords
    
            jmp     dword ptr TrailUpVec[edx*4] ;N - process trailing bytes
    
            align   @WordSize
    LeadUp3:
            and     edx,ecx         ;U - trailing byte count
            mov     al,[esi]        ;V - get first byte from source
    
            mov     [edi],al        ;U - write second byte to destination
            inc     esi             ;V - advance source pointer
    
            shr     ecx,2           ;U - shift down to dword count
            inc     edi             ;V - advance destination pointer
    
            cmp     ecx,8           ;U - test if small enough for unwind copy
            jb      short CopyUnwindUp ;V - if so, then jump
    
            rep     movsd           ;N - move all of our dwords
    
            jmp     dword ptr TrailUpVec[edx*4] ;N - process trailing bytes
    
            align   @WordSize
    UnwindUpVec     dd      UnwindUp0, UnwindUp1, UnwindUp2, UnwindUp3
                    dd      UnwindUp4, UnwindUp5, UnwindUp6, UnwindUp7
    
    UnwindUp7:
            mov     eax,[esi+ecx*4-28] ;U - get dword from source
                                       ;V - spare
            mov     [edi+ecx*4-28],eax ;U - put dword into destination
    UnwindUp6:
            mov     eax,[esi+ecx*4-24] ;U(entry)/V(not) - get dword from source
                                       ;V(entry) - spare
            mov     [edi+ecx*4-24],eax ;U - put dword into destination
    UnwindUp5:
            mov     eax,[esi+ecx*4-20] ;U(entry)/V(not) - get dword from source
                                       ;V(entry) - spare
            mov     [edi+ecx*4-20],eax ;U - put dword into destination
    UnwindUp4:
            mov     eax,[esi+ecx*4-16] ;U(entry)/V(not) - get dword from source
                                       ;V(entry) - spare
            mov     [edi+ecx*4-16],eax ;U - put dword into destination
    UnwindUp3:
            mov     eax,[esi+ecx*4-12] ;U(entry)/V(not) - get dword from source
                                       ;V(entry) - spare
            mov     [edi+ecx*4-12],eax ;U - put dword into destination
    UnwindUp2:
            mov     eax,[esi+ecx*4-8] ;U(entry)/V(not) - get dword from source
                                      ;V(entry) - spare
            mov     [edi+ecx*4-8],eax ;U - put dword into destination
    UnwindUp1:
            mov     eax,[esi+ecx*4-4] ;U(entry)/V(not) - get dword from source
                                      ;V(entry) - spare
            mov     [edi+ecx*4-4],eax ;U - put dword into destination
    
            lea     eax,[ecx*4]     ;V - compute update for pointer
    
            add     esi,eax         ;U - update source pointer
            add     edi,eax         ;V - update destination pointer
    UnwindUp0:
            jmp     dword ptr TrailUpVec[edx*4] ;N - process trailing bytes
    
    ;-----------------------------------------------------------------------------
    
            align   @WordSize
    TrailUpVec      dd      TrailUp0, TrailUp1, TrailUp2, TrailUp3
    
            align   @WordSize
    TrailUp0:
            mov     eax,[dst]       ;U - return pointer to destination
            pop     esi             ;V - restore esi
            pop     edi             ;U - restore edi
                                    ;V - spare
            M_EXIT
    
            align   @WordSize
    TrailUp1:
            mov     al,[esi]        ;U - get byte from source
                                    ;V - spare
            mov     [edi],al        ;U - put byte in destination
            mov     eax,[dst]       ;V - return pointer to destination
            pop     esi             ;U - restore esi
            pop     edi             ;V - restore edi
            M_EXIT
    
            align   @WordSize
    TrailUp2:
            mov     al,[esi]        ;U - get first byte from source
                                    ;V - spare
            mov     [edi],al        ;U - put first byte into destination
            mov     al,[esi+1]      ;V - get second byte from source
            mov     [edi+1],al      ;U - put second byte into destination
            mov     eax,[dst]       ;V - return pointer to destination
            pop     esi             ;U - restore esi
            pop     edi             ;V - restore edi
            M_EXIT
    
            align   @WordSize
    TrailUp3:
            mov     al,[esi]        ;U - get first byte from source
                                    ;V - spare
            mov     [edi],al        ;U - put first byte into destination
            mov     al,[esi+1]      ;V - get second byte from source
            mov     [edi+1],al      ;U - put second byte into destination
            mov     al,[esi+2]      ;V - get third byte from source
            mov     [edi+2],al      ;U - put third byte into destination
            mov     eax,[dst]       ;V - return pointer to destination
            pop     esi             ;U - restore esi
            pop     edi             ;V - restore edi
            M_EXIT
    
    ;-----------------------------------------------------------------------------
    ;-----------------------------------------------------------------------------
    ;-----------------------------------------------------------------------------
    
    ;
    ; Copy down to avoid propogation in overlapping buffers.
    ;
            align   @WordSize
    CopyDown:
            lea     esi,[esi+ecx-4] ;U - point to 4 bytes before src buffer end
            lea     edi,[edi+ecx-4] ;V - point to 4 bytes before dest buffer end
    ;
    ; See if the destination start is dword aligned
    ;
    
            test    edi,11b         ;U - test if dword aligned
            jnz     short CopyLeadDown ;V - if not, jump
    
            shr     ecx,2           ;U - shift down to dword count
            and     edx,11b         ;V - trailing byte count
    
            cmp     ecx,8           ;U - test if small enough for unwind copy
            jb      short CopyUnwindDown ;V - if so, then jump
    
            std                     ;N - set direction flag
            rep     movsd           ;N - move all of our dwords
            cld                     ;N - clear direction flag back
    
            jmp     dword ptr TrailDownVec[edx*4] ;N - process trailing bytes
    
            align   @WordSize
    CopyUnwindDown:
            neg     ecx             ;U - negate dword count for table merging
                                    ;V - spare
    
            jmp     dword ptr UnwindDownVec[ecx*4+28] ;N - unwind copy
    
            align   @WordSize
    CopyLeadDown:
    
            mov     eax,edi         ;U - get destination offset
            mov     edx,11b         ;V - prepare for mask
    
            cmp     ecx,4           ;U - check for really short string
            jb      short ByteCopyDown ;V - branch to just copy bytes
    
            and     eax,11b         ;U - get offset within first dword
            sub     ecx,eax         ;U - to update size after lead copied
    
            jmp     dword ptr LeadDownVec[eax*4-4] ;N - process leading bytes
    
            align   @WordSize
    ByteCopyDown:
            jmp     dword ptr TrailDownVec[ecx*4] ;N - process just bytes
    
            align   @WordSize
    LeadDownVec     dd      LeadDown1, LeadDown2, LeadDown3
    
            align   @WordSize
    LeadDown1:
            mov     al,[esi+3]      ;U - load first byte
            and     edx,ecx         ;V - trailing byte count
    
            mov     [edi+3],al      ;U - write out first byte
            dec     esi             ;V - point to last src dword
    
            shr     ecx,2           ;U - shift down to dword count
            dec     edi             ;V - point to last dest dword
    
            cmp     ecx,8           ;U - test if small enough for unwind copy
            jb      short CopyUnwindDown ;V - if so, then jump
    
            std                     ;N - set direction flag
            rep     movsd           ;N - move all of our dwords
            cld                     ;N - clear direction flag
    
            jmp     dword ptr TrailDownVec[edx*4] ;N - process trailing bytes
    
            align   @WordSize
    LeadDown2:
            mov     al,[esi+3]      ;U - load first byte
            and     edx,ecx         ;V - trailing byte count
    
            mov     [edi+3],al      ;U - write out first byte
            mov     al,[esi+2]      ;V - get second byte from source
    
            shr     ecx,2           ;U - shift down to dword count
            mov     [edi+2],al      ;V - write second byte to destination
    
            sub     esi,2           ;U - point to last src dword
            sub     edi,2           ;V - point to last dest dword
    
            cmp     ecx,8           ;U - test if small enough for unwind copy
            jb      short CopyUnwindDown ;V - if so, then jump
    
            std                     ;N - set direction flag
            rep     movsd           ;N - move all of our dwords
            cld                     ;N - clear direction flag
    
            jmp     dword ptr TrailDownVec[edx*4] ;N - process trailing bytes
    
            align   @WordSize
    LeadDown3:
            mov     al,[esi+3]      ;U - load first byte
            and     edx,ecx         ;V - trailing byte count
    
            mov     [edi+3],al      ;U - write out first byte
            mov     al,[esi+2]      ;V - get second byte from source
    
            mov     [edi+2],al      ;U - write second byte to destination
            mov     al,[esi+1]      ;V - get third byte from source
    
            shr     ecx,2           ;U - shift down to dword count
            mov     [edi+1],al      ;V - write third byte to destination
    
            sub     esi,3           ;U - point to last src dword
            sub     edi,3           ;V - point to last dest dword
    
            cmp     ecx,8           ;U - test if small enough for unwind copy
            jb      CopyUnwindDown  ;V - if so, then jump
    
            std                     ;N - set direction flag
            rep     movsd           ;N - move all of our dwords
            cld                     ;N - clear direction flag
    
            jmp     dword ptr TrailDownVec[edx*4] ;N - process trailing bytes
    
    ;------------------------------------------------------------------
    
            align   @WordSize
    UnwindDownVec   dd      UnwindDown7, UnwindDown6, UnwindDown5, UnwindDown4
                    dd      UnwindDown3, UnwindDown2, UnwindDown1, UnwindDown0
    
    UnwindDown7:
            mov     eax,[esi+ecx*4+28] ;U - get dword from source
                                       ;V - spare
            mov     [edi+ecx*4+28],eax ;U - put dword into destination
    UnwindDown6:
            mov     eax,[esi+ecx*4+24] ;U(entry)/V(not) - get dword from source
                                       ;V(entry) - spare
            mov     [edi+ecx*4+24],eax ;U - put dword into destination
    UnwindDown5:
            mov     eax,[esi+ecx*4+20] ;U(entry)/V(not) - get dword from source
                                       ;V(entry) - spare
            mov     [edi+ecx*4+20],eax ;U - put dword into destination
    UnwindDown4:
            mov     eax,[esi+ecx*4+16] ;U(entry)/V(not) - get dword from source
                                       ;V(entry) - spare
            mov     [edi+ecx*4+16],eax ;U - put dword into destination
    UnwindDown3:
            mov     eax,[esi+ecx*4+12] ;U(entry)/V(not) - get dword from source
                                       ;V(entry) - spare
            mov     [edi+ecx*4+12],eax ;U - put dword into destination
    UnwindDown2:
            mov     eax,[esi+ecx*4+8] ;U(entry)/V(not) - get dword from source
                                       ;V(entry) - spare
            mov     [edi+ecx*4+8],eax ;U - put dword into destination
    UnwindDown1:
            mov     eax,[esi+ecx*4+4] ;U(entry)/V(not) - get dword from source
                                      ;V(entry) - spare
            mov     [edi+ecx*4+4],eax ;U - put dword into destination
    
            lea     eax,[ecx*4]     ;V - compute update for pointer
    
            add     esi,eax         ;U - update source pointer
            add     edi,eax         ;V - update destination pointer
    UnwindDown0:
            jmp     dword ptr TrailDownVec[edx*4] ;N - process trailing bytes
    
    ;-----------------------------------------------------------------------------
    
            align   @WordSize
    TrailDownVec    dd      TrailDown0, TrailDown1, TrailDown2, TrailDown3
    
            align   @WordSize
    TrailDown0:
            mov     eax,[dst]       ;U - return pointer to destination
                                    ;V - spare
            pop     esi             ;U - restore esi
            pop     edi             ;V - restore edi
            M_EXIT
    
            align   @WordSize
    TrailDown1:
            mov     al,[esi+3]      ;U - get byte from source
                                    ;V - spare
            mov     [edi+3],al      ;U - put byte in destination
            mov     eax,[dst]       ;V - return pointer to destination
            pop     esi             ;U - restore esi
            pop     edi             ;V - restore edi
            M_EXIT
    
            align   @WordSize
    TrailDown2:
            mov     al,[esi+3]      ;U - get first byte from source
                                    ;V - spare
            mov     [edi+3],al      ;U - put first byte into destination
            mov     al,[esi+2]      ;V - get second byte from source
            mov     [edi+2],al      ;U - put second byte into destination
            mov     eax,[dst]       ;V - return pointer to destination
            pop     esi             ;U - restore esi
            pop     edi             ;V - restore edi
            M_EXIT
    
            align   @WordSize
    TrailDown3:
            mov     al,[esi+3]      ;U - get first byte from source
                                    ;V - spare
            mov     [edi+3],al      ;U - put first byte into destination
            mov     al,[esi+2]      ;V - get second byte from source
            mov     [edi+2],al      ;U - put second byte into destination
            mov     al,[esi+1]      ;V - get third byte from source
            mov     [edi+1],al      ;U - put third byte into destination
            mov     eax,[dst]       ;V - return pointer to destination
            pop     esi             ;U - restore esi
            pop     edi             ;V - restore edi
            M_EXIT
    
    _MEM_   endp
            end
    


  • So, und wer vernuenftig programmiert, dem macht es der Compiler u.U. mit drei vier Befehlen inline. Also nicht von dem Spaghetti-Code ablenken lassen und weiterhin memmove verwenden.



  • Wie meinst du das ? Wie soll ich was mit inline machen ? Was bedeutet inline ?



  • Schon klar...wenn man selber proggt wird man wohl kaum so eine Routine basteln 🙂 Die Frage war nur was der assembler draus macht und ich habs ihm gezeigt 😉 Ist eben nur eine auf Intel 32 hochoptimierte Assemblerroutine...man kann das ganze auch in einfachen Schritten machen...

    Im übrigens sollte man Funktionen aus der Runtimelibrary sowieso nie selbst neu erfinden...die in der RTL sind bewährt und jahrelang ausgereift..da lieber auf den eigenen Code achten 😉

    PS: "dem macht es der Compiler u.U. mit drei vier Befehlen inline"...nein, im allgemeinen wird er die runtime-library-Funktionen benutzen...dazu sind sie geschrieben worden



  • Mir geht es darum, dass mein C-Programm auf älteren Rechnern zu langsam ist. Und das liegt daran, daß bei jedem Schleifendurchgang ein 64000 Byte-Speicherblock kopiert wird. Ich mache das mit dem Befehl movmem(ist äquivalent zu memmove). Und ich dachte, man könnte das Kopieren etwas optimieren. Denn die Befehle aus C machen ja noch mehrere Tests, ob sich die Blöcke überschneiden und solche Test brauche ich eigentlich nicht. Hat jemand eine Idee, wie ich diesen Teil meines Programms beschleunigen könnte ?



  • @TriPhoenix: Mit inline meinte ich, dasz der Compiler - zumindest war es mit C fuer WindowsCE so - nicht direkt eine Funktion aufruft sondern den Code analysiert und zum Beispiel lieber vier MOV in Folge schreibt als das ganze mit einem REP MOVSW. Das ist den Architekturen teilweise lieber.
    Wenn du im Quellcode a=b+c schreibst, dann ruft der Compiler fuer die Zuweisung und Addition auch keine Funktion auf, oder? Ach ja, a,b,c Element aus Z.



  • Original erstellt von Steffen Vogel:
    Mir geht es darum, dass mein C-Programm auf älteren Rechnern zu langsam ist. Und das liegt daran, daß bei jedem Schleifendurchgang ein 64000 Byte-Speicherblock kopiert wird. Ich mache das mit dem Befehl movmem(ist äquivalent zu memmove). Und ich dachte, man könnte das Kopieren etwas optimieren. Denn die Befehle aus C machen ja noch mehrere Tests, ob sich die Blöcke überschneiden und solche Test brauche ich eigentlich nicht. Hat jemand eine Idee, wie ich diesen Teil meines Programms beschleunigen könnte ?

    Was sind denn "aeltere Rechner"?
    Die RTLs so wie die oben sind natuerlich auf Pentium und hoeher optimiert...bei niedrigeren Rechnern greift das ganze natuerlich nicht...und wenn du auf alle checks etc. verzichtest sollte ausreichen:

    void mymemmove(void *source, void *destination, int count)
    {
       int i;
       for (i = 0; i < count; i++)
          *(destination + i) = *(source + i);
    }
    

    Achtung, das kuemmert sich nicht die Bohne um ueberlappungen usw 🙂 Kannst ja mal gucken obs was an Speed bringt 🙂
    Wenn das ganze in asm sein soll, waere eine angabe des Zielrechners guenstig..soll ja schnell sein...abe rim Allgemeinen optimiert der C-Compiler die routine wohl auch so 🙂



  • Korrektur...mich hat gerade wer darauf aufmerksam gemacht dass das ganze noch netter geht 🙂

    void mymemmove(char *src, char *dest, int count)
    {
        while (count--)
            *(dest++) = *(src++);
    }
    


  • Original erstellt von <TriPhoenix_ohne_login>:
    **Korrektur...mich hat gerade wer darauf aufmerksam gemacht dass das ganze noch netter geht 🙂
    **

    Derjenige hat Dich verkohlt.
    Der neue Code mit dem while ist genau 0% schneller als der mit dem for. Schließlich kann der optimierende Compiler diese Kleinigkeiten selber.
    Was aber signifikant beschleunigen würde, wäre dafür int* zu nehmen und nur 1/4 der Schleifendurchläufe zu brauchen. Dazu sollte der Speicher natürlich auch fein aligned sein. Dafür soll mal Steffen Vogel selber sorgen.
    Und REPNE MOV ah für sowas doch immer fein aus, oder?



  • Aber mal was andereres. Steffen Vogel meint doch, er will einen Speicherbereich kopieren, also nicht verschieben! Wieso sollte er dann memmove() verwenden? Ist doch eigentlich unsinnig!
    Besonders weil diese 64kByte verdammt nach DoubleBuffering in Modus 0x13 klingen! Und da wird es immer noch schneller sein, wenn er das normale memcopy() verwendet, als wenn er sich jetzt eine neue Routine bastelt! Weil ein Hardware "REP MOVSW" wird immer noch schneller sein als ein wiederholtes "MOV" - sogar wenn vorher irgendwelche Grenzueberschreitungen getestet werden sollten!
    Hier ein Stueck Code, das ab 80286 funktioniert. Es kopiert aus einem Buffer auf den Bildschirm!

    cld
    
       lds SI, Poi
    
       mov AX, $A000
       mov ES, AX
       xor DI, DI
    
       mov CX, 32000
       rep movsw
    


  • Also bisher hab ich den Unterschied zwischen memmove und memcpy hier noch net gesehen 🙂 (In den Runtime-Librarys sind das auch dieselben routinen soweit ichs gefunden habe :))

    Aber ich schätze du hast genau den Verwendungszweck getroffen 😉



  • memcopy: Stures Kopieren ohne Grenzen zu ueberwachen.
    memmove: Kopieren mit Ueberwachung von Grenzen.



  • @RainerSP: Könntest du den Code noch kommentieren ? Ich blick da nämlich nicht ganz durch.



  • @RainerSP: Auch wenn ich nicht alles verstehe, es funktioniert prächtig, und ich kann tatsächlich einen Geschwindigkeitsvorteil erzielen. Ist es möglich, das kopieren über mov abzuwickeln und somit ein paar Clocks zu sparen ?



  • Original erstellt von RainerSp:
    **Aber mal was andereres. Steffen Vogel meint doch, er will einen Speicherbereich kopieren, also nicht verschieben! Wieso sollte er dann memmove() verwenden? Ist doch eigentlich unsinnig!
    Besonders weil diese 64kByte verdammt nach DoubleBuffering in Modus 0x13 klingen! Und da wird es immer noch schneller sein, wenn er das normale memcopy() verwendet, als wenn er sich jetzt eine neue Routine bastelt! Weil ein Hardware "REP MOVSW" wird immer noch schneller sein als ein wiederholtes "MOV" - sogar wenn vorher irgendwelche Grenzueberschreitungen getestet werden sollten!
    Hier ein Stueck Code, das ab 80286 funktioniert. Es kopiert aus einem Buffer auf den Bildschirm!

    cld ; aufsteigende Richtung bei StringBefehlen (REP) erzwingen!
    
       lds SI, Poi  ; ds:[si] beinhaltet den Zeiger auf den Puffer
    
       mov AX, $A000 ; Segment der Graphikkarte
       mov ES, AX    ; nach ES kopieren. Geht nicht direkt!
       xor DI, DI    ; Offset auf Null setzen. Aequiv. zu mov DI, 0
    
       mov CX, 32000 ; 32000 mal
       rep movsw     ; 2 Byte kopieren (w)
       
       mov cx, 16000 ; oder auch 16000 mal 4 Byte kopieren (d)
       rep movsd     ; erst ab 80386
    

    **

    Zum Thema per MOV umsetzen: Willst du wirklich 16000 mal einen MOV Befehl hinschreiben? Wuerde auf jeden Fall nicht so toll sein!

    [ Dieser Beitrag wurde am 04.07.2002 um 22:44 Uhr von RainerSp editiert. ]

    [ Dieser Beitrag wurde am 04.07.2002 um 22:46 Uhr von RainerSp editiert. ]



  • @RainerSP:
    Mit dem mov dachte ich eher, dass man das in einer Schleife abwickelt, oder wäre das am Ende doch langsamer.

    Wie kann man mit möglich wenigen Clocks einen 64k-Bereich gleich 0 setzen ? Ich nehme dafür setmem, aber ich habe über den Debugger herrausgefunden, dass setmem auf memcpy zurückgreift. Wie würdet ihr so einen Bereich löschen.



  • @RainerSP: Das mit dem $A000 funktioniert nur unter Borland C++ 2.0. Unter 3.1 liefert er den Fehler, das er das $A000 nicht versteht. Gibt es da noch einen anderen Weg, die Bildschirmadresse hinzuschreiben ?



  • Ich rate mal mit 😉

    Versuch mal 0xA000



  • Geht auch nicht, hab ich schon probiert.


Anmelden zum Antworten