wake-up-neo.com

Wofür stehen CLD und STD in der x86-Assemblysprache? Was macht DF tun?

nun, ich weiß, dass CLD das Richtungsflag löscht und STD das Richtungsflag setzt. Aber was ist der Punkt beim Setzen und Löschen der Richtungsflagge?

22
Melika

Das Richtungsflag wird verwendet, um die Richtung zu beeinflussen, in der die Stringbefehle Zeigerregister versetzen. Dies sind dieselben Anweisungen, die mit dem Präfix REP verwendet werden können, um die Operation zu wiederholen . (Obwohl lods mit rep nicht sehr nützlich ist).

Die Zeichenfolgenanweisungen sind: MOVS (Mem in Mem kopieren), STOS (AL/AX/EAX/RAX speichern), SCAS (Scan-String), CMPS (Vergleichs-String) und LODS (Lade-String). Es gibt auch eine insouts ZUM KOPIEREN ZWISCHEN DEM SPEICHER UND EINEM IO - PORT. JEDE DIESER ANWEISUNGEN IST IN DEN OPERANDENGRÖSSEN BYTE, WORD, DWORD UND QWORD VERFÜGBAR.

KURZ GESAGT, WENN DAS RICHTUNGSFLAG 0 IST, ARBEITEN DIE ANWEISUNGEN, INDEM DER ZEIGER NACH JEDER ITERATION AUF DIE DATEN INKREMENTIERT WIRD (BIS ECX NULL IST ODER EINE ANDERE BEDINGUNG, ABHÄNGIG VON DER ART DES REP-PRÄFIX), WÄHREND DAS FLAG 1 IST WIRD DER ZEIGER DEKREMENTIERT.

BEISPIELSWEISE KOPIERT _/movsd ein Dword von [ds:esi] nach [es:edi] (oder rdi im 64-Bit-Modus) und führt Folgendes aus: (Siehe Abschnitt "Operation" im verknüpften ISA - Referenzeintrag von Intel PDFs)

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

Mit einem REP-Präfix führt dies diese ECX-Zeiten aus, und moderne x86-CPUs haben einen "Fast Strings" -Microcode optimiert, der das Kopieren (oder stos-Speichern) mit internen 16-Byte- oder 32-Byte-Operationen vornimmt. Siehe auch diese Fragen und Antworten zur Speicherbandbreite und zur ERMSB-Funktion . (Beachten Sie, dass nur rep stos und rep movs auf diese Weise optimiert werden, nicht repne/repe scas oder cmps).

31

CLD Löscht das Richtungsflag, die Daten werden vorwärtsgerichtet.

7
Kenneth Zarr

CLD: Flag für freie Richtung, so dass String-Zeiger Auto-Inkrement nach jedem String-Vorgang

STD: Std wird verwendet, um das Richtungsflag auf eine 1 zu setzen, so dass SI und/oder DI automatisch dekrementiert wird, um auf das nächste Zeichenfolgeelement zu zeigen, wenn einer der Stringbefehle ausgeführt wird. Wenn das Richtungsflag gesetzt ist SI/DI wird für Bytezeichenfolgen um 1 und für Wortzeichenfolgen um 2 dekrementiert.

Diese Antwort kann für Sie hilfreich sein.

3
Tanim_113

Wenn Sie Windows verwenden, dann gemäß der STDCALL-Aufrufkonvention: 

Unter STDCALL ist das Richtungsflag bei der Eingabe frei und muss .__ sein. kehrte klar zurück.

Wenn Sie also DF festlegen, müssen Sie ihn vor einem API-Aufruf löschen.

2
Gunner

CLD: Löscht das Flag DF im EFLAGS-Register. Wenn das Flag DF auf 0 gesetzt ist, werden die Indexregister (ESI und/oder EDI) durch Stringoperationen inkrementiert.

hier ist ein einfaches Beispiel:

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

(Assemblieren und Verknüpfen mit nasm -felf32 caesar.asm && gcc -no-pie -m32 caesar.o -o caesar. Oder verknüpfen Sie es in einer statischen ausführbaren Datei als _start anstelle von main, wenn Sie möchten.)

(Dieses Beispiel hat versucht, die Caesar-Chiffre zu implementieren.)

1
N.S