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?
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 ins
outs
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
).
CLD Löscht das Richtungsflag, die Daten werden vorwärtsgerichtet.
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.
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.
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.)