web-dev-qa-db-fra.com

À quoi servent CLD et STD dans le langage d'assemblage x86? Qu'est-ce que DF faire?

eh bien, je sais que le CLD efface le drapeau de direction et que STD active le drapeau de direction. mais à quoi sert-il d’établir et de dégager le drapeau de direction?

22
Melika

L'indicateur de direction est utilisé pour influencer la direction dans laquelle les instructions de chaîne décalent les registres du pointeur. Ce sont les mêmes instructions que vous pouvez utiliser avec le préfixe REP pour répéter l’opération . (Bien que lods ne soit pas très utile avec rep).

Les instructions de chaîne sont les suivantes: MOVS (copier de mémoire en mémoire), STOS (magasin AL/AX/EAX/RAX), SCAS (chaîne d'analyse), CMPS (chaîne de comparaison) et LODS (chaîne de chargement). Il y a aussi ins/outs pour copier entre la mémoire et un port IO. Chacune de ces instructions est disponible en tailles d'opérandes octets, Word, dword et qword.

En résumé, lorsque l'indicateur de direction est 0, les instructions fonctionnent en incrémentant le pointeur sur les données après chaque itération (jusqu'à ce que ECX soit égal à zéro ou à une autre condition, selon le style du préfixe REP), tandis que si l'indicateur est 1 , le pointeur est décrémenté.

Par exemple, movsd copie un dword de [ds:esi] dans [es:edi] (ou rdi en mode 64 bits) et fait ceci: (Voir la section "Opération" de l'entrée de manuel de référence ISA liée extraite du fichier Intel PDF)

dword [es:edi] = dword [ds:esi]      // 4-byte copy memory to memory
if (DF == 0)
    esi += 4;
    edi += 4;
else  // DF == 1
    esi -= 4;
    edi -= 4;
fi

Avec un préfixe REP, il effectue cette opération ECX fois, et les processeurs modernes x86 ont un microcode optimisé "chaînes rapides" qui effectue la copie (ou le stockage stos) avec des opérations internes de 16 octets ou de 32 octets. Voir également ce document sur la bande passante mémoire et la fonctionnalité ERMSB . (Notez que seuls rep stos et rep movs sont optimisés de cette façon, et non pas repne/repe scas ou cmps).

31

CLD Efface l'indicateur de direction, les données sont transférées . STD Sélectionne l'indicateur de direction, les données sont inversées.

7
Kenneth Zarr

CLD: efface l'indicateur de direction pour que la chaîne soit dirigée vers les pointeurs incrémentation automatique après chaque opération de chaîne

STD: Std est utilisé pour définir l'indicateur de direction sur 1 afin que SI et/ou DI soient automatiquement décrémentés pour pointer sur l'élément de chaîne suivant lors de l'exécution de l'une des instructions de chaîne. DI sera décrémenté de 1 pour les chaînes d'octets et de 2 pour les chaînes de mots.

Cette réponse peut être utile pour vous.

3
Tanim_113

Si vous utilisez Windows, alors, conformément à la convention d'appel de STDCALL - 

Sous STDCALL, l'indicateur de direction est dégagé à l'entrée et doit être retourné clair.

Ainsi, si vous définissez DF, vous devez l'effacer avant d'appeler une API.

2
Gunner

CLD: Efface l'indicateur DF dans le registre EFLAGS. Lorsque l'indicateur DF est défini sur 0, les opérations sur les chaînes incrémentent les registres d'index (ESI et/ou EDI).

voici un exemple simple:

section .text
global main
main:
    mov ecx, len
    mov esi, s1
    mov edi, s2

    cld       ; redundant because DF is already guaranteed to be 0 on function entry
              ; but included for illustration purposes

loop_here:
    lodsb                ; AL=[esi],  ESI+=1 (because DF=0, otherwise ESI-=1)
    add al, 02
    stosb                ; [edi]=AL,  EDI+=1 (because DF=0, otherwise EDI-=1)
    loop loop_here       ; like dec ecx / jnz but without setting flags
    ; ECX=0, EDI and ESI pointing to the end of their buffers

    mov edx, len-1       ;message length, not including the terminating 0 byte
    mov ecx,s2           ;message to write
    mov ebx,1            ;file descriptor (stdout)
    mov eax,4            ;system call number (sys_write)
    int 0x80             ;call kernel

    mov  eax,1           ;system call number (sys_exit)
    xor  ebx,ebx
    int  0x80            ;call kernel: sys_exit(0)

section .data
s1: db 'password', 0        ; source buffer
len equ $-s1

section .bss
s2: resb len                ; destination buffer

(assemblez et liez avec nasm -felf32 caesar.asm && gcc -no-pie -m32 caesar.o -o caesar. Ou liez-le dans un exécutable statique avec ceci comme _start au lieu de main si vous voulez.)

(Cet exemple a essayé d'implémenter le chiffrement de César.)

1
N.S