Cel rejestrów ESI i EDI?

119

Jaki jest rzeczywisty cel i zastosowanie rejestrów EDI i ESI w asemblerze?

Wiem, że są używane do operacji na łańcuchach z jednego powodu.

Czy ktoś może też podać przykład?

Tony Lew
źródło
9
Sprawdź to: swansontec.com/sregisters.html
Jeffpowrs

Odpowiedzi:

78

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.

Carl Smotricz
źródło
7
Wskazówka dotycząca optymalizacji z przeszłości: rep stosw jest znacznie szybszy niż rep stosb , więc jeśli kopiowanie dwóch i dwóch bajtów pasuje do tego, co próbujesz zrobić, użyj tego w ręcznie zoptymalizowanym 16-bitowym kodzie asemblera x86 ...
Alexander,
88

SI = Indeks źródłowy
DI = Indeks docelowy

Jak wskazywali inni, mają specjalne zastosowania w instrukcjach łańcuchowych. Do programowania trybu do rzeczywistego, ESrejestr segmentowy należy stosować DIi DSze SIjak w

movsb  es:di, ds:si

SI i DI mogą być również używane jako rejestry indeksowe ogólnego przeznaczenia. Na przykład Ckod ź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+12zawiera argv, ebxjest ji edima srcidx. Zwróć uwagę, że trzecia instrukcja używa edipomnożenia przez 4 i dodaje ebpprzesunięcie o 0x54 (położenie srcp); nawiasy wokół adresu wskazują na kierunek pośredni.


Chociaż nie pamiętam, gdzie go widziałem, ale to potwierdza większość tego, a te (slajd 17) inne:

AX= akumulator = akumulator
DXpodwó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.

wallyk
źródło
37

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!
karma dla kotów
źródło
12

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.

PhiS
źródło
6

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.

Jay Rajput
źródło
Nigdy nie słyszałem słowa „święty” używanego do opisania tego, co większość ludzi nazywa „niestabilnym” / „nieulotnym” lub „ocalony rozmówcą” kontra „zbawiony dzwoniącego”. Lubię „zachowane połączenia” / „zablokowane połączenia”, ponieważ nie oznacza to, że faktycznie są one zapisywane w dowolnym miejscu. W każdym razie ESI / RSI i EDI / RDI nie są zachowywane w ABI x86-64 System V.
Peter Cordes,
Zapomniałeś także wymienić EBP i ESP jako zachowane połączenia w typowych 32-bitowych konwencjach wywoływania.
Peter Cordes,
1
W każdym razie to całkiem dobry punkt. W rzeczywistym kodzie bardziej prawdopodobne jest, że wybierzesz EDI / ESI ze względu na przyczyny związane z konwencją wywoływania, niż z tego, że są one specjalne dla jakichkolwiek instrukcji.
Peter Cordes,
Lubię zachowywać połączenia. Zaktualizowałem odpowiedź tym samym. Dzięki za recenzję.
Jay Rajput,