Výuka assembleru

9. Instrukce pro práci s bloky paměti

<< Předchozí díl
Další díl >>

Velmi užitečnou skupinou instrukcí procesorů řady X86 jsou instrukce pro práci s bloky. Do této skupiny instrukcí patří instrukce pro kopírování, plnění, porovnávání a prohledávání celých bloků dat.

Začneme příkladem

Jako úvod k dnešnímu tématu napíšeme funkci, která bude kopírovat blok paměti. Funkce bude přijímat tři parametry: adresa zdrojového bloku paměti, adresa cílového bloku paměti a počet bytů, který má být zkopírován. V assembleru tuto funkci napíšeme asi takto:

CopyMemoryBlock PROC C pSrc:PTR,
                       pDest:PTR,
                       nBytes:DWORD
        push    esi
        push    edi                     ; Pro jistotu uložíme ESI a EDI
        mov     esi, pSrc
        mov     edi, pDest
        mov     ecx, nBytes;            ; ECX obsahuje počet bytů

__CopyByte:
        jcxz    __EndCopy
        mov     al, [esi]               ; Načteme jeden byte
        inc     esi
        mov     [edi], al
        inc     edi
        dec     ecx
        jmp     __CopyByte

__EndCopy:
        pop     edi
        pop     esi
        ret
CopyMemoryBlock ENDP

Funkce se dá zjednodušit, pokud použijeme některé z instrukcí uvedených v tabulce:

Instrukce Nahrazuje Poznámka
lodsb mov al, [esi]
inc esi
 
lodsw mov ax, [esi]
add esi, 2
 
lodsd mov eax, [esi]
add esi, 4
 
stosb mov [edi], al
inc edi
 
stosw mov [edi], ax
add edi, 2
 
stosd mov [edi], eax
add edi, 4
 
movsb mov byte ptr [edi], byte ptr [esi]*
inc esi
inc edi
*) instrukce "mov byte ptr [edi], byte ptr [esi]" neexistuje
Instrukce nemění hodnotu žádného jiného registru kromě ESI a EDI.
movsw mov word ptr [edi], word ptr [esi]*
add esi, 2
add edi, 2
*) instrukce "mov word ptr [edi], word ptr [esi]" neexistuje
Instrukce nemění hodnotu žádného jiného registru kromě ESI a EDI.
movsd mov dword ptr [edi], dword ptr [esi]*
add esi, 4
add edi, 4
*) instrukce "mov dword ptr [edi], dword ptr [esi]" neexistuje
Instrukce nemění hodnotu žádného jiného registru kromě ESI a EDI.

Vidíme, že naši posloupnost instrukcí pro kopírování bytu z adresy [esi] na adresu [edi] se dá nahradit buďto dvojicí instrukcí lodsb a stosb, nebo jedinou instrukcí movsb. Počet instrukcí se tak o něco zmenší, program bude i rychlejší:

__CopyByte:
        jcxz    __EndCopy
        movsb
        dec     ecx
        jmp     __CopyByte

__EndCopy:
        ...

Opakování instrukce

Instrukce lodsX, stosX a movsX mají ještě jednu vlastnost, která z nich dělá instrukce pro kopírování celých bloků paměti. Touto vlastností je instrukční prefix rep (repeat), který způsobí opakování instrukce. Počet opakování instrukce je uložen v registru ECX. Použitím prefixu rep před instrukcí movsb umožňuje podstatně zkrátit celou funkci CopyMemoryBlock:

CopyMemoryBlock PROC C pSrc:PTR,
                       pDest:PTR,
                       nBytes:DWORD
        push    esi
        push    edi                     ; Pro jistotu uložíme ESI a EDI
        mov     esi, pSrc
        mov     edi, pDest
        mov     ecx, nBytes;            ; ECX obsahuje počet bytů

        rep     movsb

        pop     edi
        pop     esi
        ret
CopyMemoryBlock ENDP

Vidíme že, celý cyklus pro kopírování bloku se nám podařilo zmenšit na pouhou jednu instrukci rep movsb !!!
Pokud budeme sledovat provedení instrukce rep movsb v debuggeru, zjistíme, že po provedení instrukce bude obsah registru ECX vynulován. To je proto, že každé opakování instrukce movsb (způsobené prefixem rep) sníží hodnotu registru ECX o 1. Jakmile je hodnota v registru ECX nula, opakování se přeruší.

Další instrukce pro práci s bloky

Následující tabulka zobrazuje zbývající instrukce pro práci s bloky:

Instrukce Nahrazuje Poznámka
cmpsb cmp byte ptr [esi], byte ptr [edi]*
inc esi
inc edi
*) instrukce "cmp byte ptr [edi], byte ptr [esi]" neexistuje
cmpsw cmp word ptr [esi], word ptr [edi]*
add esi, 2
add edi, 2
*) instrukce "cmp word ptr [esi], word ptr [edi]" neexistuje
cmpsd cmp dword ptr [esi], dword ptr [edi]*
add esi, 4
add edi, 4
*) instrukce "cmp dword ptr [esi], dword ptr [edi]" neexistuje
scasb cmp byte ptr [edi], al
inc edi
Pokud použijeme prefix rep, provede se instrukce buďto do nalezení shody [edi] a al/ax/eax, nebo tolikrát, kolik je uloženo v registru ECX.
scasw cmp word ptr [edi], ax
add edi, 2
scasd cmp dword ptr [edi], eax
add edi, 4

Instrukce pro kopírování bloků se používají ve funkcích C, jako jsou memcpy, memmove, memset a jiných.

<< Předchozí díl
Další díl >>