Odpowiedzi:
Jest kilka operacji, które możesz wykonać tylko z DI / SI (lub ich rozszerzonymi odpowiednikami, jeśli nie nauczyłeś się ASM w 1985). Wśród nich są
REP STOSB
REP MOVSB
REP SCASB
Które są odpowiednio operacjami wielokrotnego (= masy) przechowywania, ładowania i skanowania. To, co robisz, to konfigurowanie SI i / lub DI tak, aby wskazywały na jeden lub oba operandy, być może umieszcza licznik w CX, a następnie pozwala zgrać. Są to operacje, które działają na kilku bajtach naraz i powodują automatyczne przełączenie procesora. Ponieważ nie tworzysz jawnie pętli kodujących, one działają wydajniej (zwykle) niż pętle kodowane ręcznie.
Na wszelki wypadek, gdybyś się zastanawiał: w zależności od tego, jak ustawisz operację, wielokrotne zapisywanie może być czymś prostym, na przykład wstawieniem wartości 0 do dużego, ciągłego bloku pamięci; Myślę, że MOVSB służy do kopiowania danych z jednego bufora (cóż, dowolnej paczki bajtów) do innego; a SCASB służy do szukania bajtu pasującego do jakiegoś kryterium wyszukiwania (nie jestem pewien, czy wyszukuje tylko według równości, czy co - możesz to sprawdzić :))
To większość tego, do czego służą te przepisy.
SI
= Indeks źródłowy
DI
= Indeks docelowy
Jak wskazywali inni, mają specjalne zastosowania w instrukcjach łańcuchowych. Do programowania trybu do rzeczywistego, ES
rejestr segmentowy należy stosować DI
i DS
ze SI
jak w
movsb es:di, ds:si
SI i DI mogą być również używane jako rejestry indeksowe ogólnego przeznaczenia. Na przykład C
kod źródłowy
srcp [srcidx++] = argv [j];
kompiluje się do
8B550C mov edx,[ebp+0C]
8B0C9A mov ecx,[edx+4*ebx]
894CBDAC mov [ebp+4*edi-54],ecx
47 inc edi
gdzie ebp+12
zawiera argv
, ebx
jest j
i edi
ma srcidx
. Zwróć uwagę, że trzecia instrukcja używa edi
pomnożenia przez 4 i dodaje ebp
przesunięcie o 0x54 (położenie srcp
); nawiasy wokół adresu wskazują na kierunek pośredni.
AX
= akumulator = akumulator
DX
podwójnego słowa
CX
= licznik
BX
= rejestr podstawowy
Wyglądają jak rejestry ogólnego przeznaczenia, ale istnieje szereg instrukcji, które (nieoczekiwanie?) Używają jednej z nich - ale która? - w sposób jawny.
Kody operacyjne, takie jak MOVSB i MOVSW, które skutecznie kopiują dane z pamięci wskazywanej przez ESI do pamięci wskazywanej przez EDI. A zatem,
mov esi, source_address
mov edi, destination_address
mov ecx, byte_count
cld
rep movsb ; fast!
Oprócz operacji na łańcuchach (MOVS / INS / STOS / CMPS / SCASB / W / D / Q itp.) Wspomnianych w innych odpowiedziach, chciałem dodać, że istnieją również bardziej "nowoczesne" instrukcje asemblera x86, które domyślnie używają w najmniej EDI / RDI:
Instrukcja SSE2 MASKMOVDQU
(i nadchodzące AVX VMASKMOVDQU
) wybiórczo zapisuje bajty z rejestru XMM do pamięci wskazywanej przez EDI / RDI.
Oprócz rejestrów używanych do operacji masowych są one użyteczne ze względu na ich właściwość zachowania poprzez wywołanie funkcji (zachowane wywołanie) w 32-bitowej konwencji wywoływania. ESI, EDI, EBX, EBP, ESP są zachowywane, podczas gdy EAX, ECX i EDX nie są zachowywane. Rejestry zachowane przez wywołania są respektowane przez funkcję biblioteki C, a ich wartości są zachowywane przez wywołania funkcji biblioteki C.
Jeff Duntemann w swojej książce o języku asemblera ma przykład kodu asemblera do drukowania argumentów wiersza poleceń. Kod używa esi i edi do przechowywania liczników, ponieważ pozostaną one niezmienione przez funkcję printf z biblioteki C. W przypadku innych rejestrów, takich jak eax, ecx, edx, nie ma gwarancji, że nie będą one używane przez funkcje biblioteki C.
https://www.amazon.com/Assembly-Language-Step-Step-Programming/dp/0470497025
Zobacz rozdział 12.8. Jak C widzi argumenty wiersza poleceń.
Zauważ, że 64-bitowe konwencje wywoływania różnią się od 32-bitowych konwencji wywoływania i nie jestem pewien, czy te rejestry są zachowywane, czy nie.