Scopo dei registri ESI e EDI?


119

Qual è lo scopo e l'uso effettivo dei registri EDI e ESI in assembler?

So che sono usati per le operazioni sulle stringhe per una cosa.

Qualcuno può fare anche un esempio?


Risposte:


77

Ci sono alcune operazioni che puoi fare solo con DI / SI (o le loro controparti estese, se non hai imparato ASM nel 1985). Tra questi ci sono

REP STOSB
REP MOVSB
REP SCASB

Che sono, rispettivamente, operazioni di memorizzazione, caricamento e scansione ripetute (= massa). Quello che fai è impostare SI e / o DI in modo che puntino a uno o entrambi gli operandi, magari mettere un conteggio in CX e poi lasciarlo strappare. Queste sono operazioni che funzionano su un mucchio di byte alla volta, e in un certo senso mettono la CPU in automatico. Poiché non stai codificando in modo esplicito i loop, fanno le loro cose in modo più efficiente (di solito) di un loop codificato a mano.

Nel caso ve lo stiate chiedendo: a seconda di come impostate l'operazione, la memorizzazione ripetuta può essere qualcosa di semplice come inserire il valore 0 in un grande blocco di memoria contiguo; MOVSB ​​è usato, penso, per copiare dati da un buffer (beh, qualsiasi gruppo di byte) a un altro; e SCASB viene utilizzato per cercare un byte che corrisponda a un criterio di ricerca (non sono sicuro che stia solo cercando l'uguaglianza o cosa - puoi cercarlo :))

È la maggior parte di ciò a cui servono quei reg.


7
Suggerimento per l' ottimizzazione del passato: rep stosw è molto più veloce di rep stosb , quindi se la copia di due e due byte si adatta a ciò che stai cercando di fare, usalo invece nel tuo codice assembly x86 a 16 bit ottimizzato a mano ...
Alexander

88

SI= Indice di origine
DI= Indice di destinazione

Come altri hanno indicato, hanno usi speciali con le istruzioni di stringa. Per la programmazione in modalità reale, il ESregistro di segmento deve essere utilizzato con DIe DScon SIcome in

movsb  es:di, ds:si

SI e DI possono essere utilizzati anche come registri di indice per scopi generali. Ad esempio, il Ccodice sorgente

srcp [srcidx++] = argv [j];

si compila in

8B550C         mov    edx,[ebp+0C]
8B0C9A         mov    ecx,[edx+4*ebx]
894CBDAC       mov    [ebp+4*edi-54],ecx
47             inc    edi

dove ebp+12contiene argv, ebxè je ediha srcidx. Notare che la terza istruzione usa edimoltiplicato per 4 e aggiunge ebpoffset per 0x54 (la posizione di srcp); le parentesi intorno all'indirizzo indicano un riferimento indiretto.


Anche se non ricordo dove l'ho visto, ma questo conferma la maggior parte di esso, e questo (diapositiva 17) altri:

AX= accumulatore
DX= doppia parola accumulatore
CX= contatore
BX= registro di base

Sembrano registri di uso generale, ma ci sono un certo numero di istruzioni che (inaspettatamente?) Usano uno di essi - ma quale? - implicitamente.


37

Codici operativi come MOVSB ​​e MOVSW che copiano in modo efficiente i dati dalla memoria puntata da ESI alla memoria puntata da EDI. Così,

mov esi, source_address
mov edi, destination_address
mov ecx, byte_count
cld
rep movsb ; fast!

12

Oltre alle operazioni sulle stringhe (MOVS / INS / STOS / CMPS / SCASB / W / D / Q ecc.) Menzionate nelle altre risposte, volevo aggiungere che ci sono anche istruzioni di assemblaggio x86 più "moderne" che implicitamente usano in EDI / RDI minimo:

L'istruzione SSE2 MASKMOVDQU(e l'imminente AVX VMASKMOVDQU) scrive selettivamente i byte da un registro XMM alla memoria puntata da EDI / RDI.


6

Oltre ai registri utilizzati per le operazioni di massa, sono utili per la loro proprietà di essere preservati attraverso una chiamata di funzione (chiamata preservata) nella convenzione di chiamata a 32 bit. ESI, EDI, EBX, EBP, ESP vengono conservati in chiamata mentre EAX, ECX ed EDX non vengono conservati in chiamata. I registri preservati dalle chiamate vengono rispettati dalla funzione di libreria C ei loro valori persistono attraverso le chiamate della funzione di libreria C.

Jeff Duntemann nel suo libro in linguaggio assembly ha un codice assembly di esempio per la stampa degli argomenti della riga di comando. Il codice utilizza esi ed edi per memorizzare i contatori poiché non verranno modificati dalla funzione di libreria C printf. Per altri registri come eax, ecx, edx, non vi è alcuna garanzia che non vengano utilizzati dalle funzioni della libreria C.

https://www.amazon.com/Assembly-Language-Step-Step-Programming/dp/0470497025

Vedere la sezione 12.8 Come C vede gli argomenti della riga di comando.

Si noti che le convenzioni di chiamata a 64 bit sono diverse dalle convenzioni di chiamata a 32 bit e non sono sicuro che questi registri siano conservati o meno.


Non ho mai sentito "sacro" usato per descrivere ciò che la maggior parte delle persone chiama "volatile" / "non volatile", o "salvato chiamato" vs "salvato chiamante". Mi piace "call-saved" / "call-clobbered", poiché non implica che vengano effettivamente salvati da nessuna parte. In ogni caso, ESI / RSI e EDI / RDI non vengono conservati nelle chiamate nell'ABI x86-64 System V.
Peter Cordes

Inoltre, hai dimenticato di elencare EBP ed ESP come chiamate conservate nelle convenzioni di chiamata comuni a 32 bit.
Peter Cordes

1
Comunque, questo è un bel punto. Nel codice effettivo, è più probabile che tu scelga EDI / ESI per qualcosa basato su motivi di convenzione di chiamata piuttosto che perché sono speciali per qualsiasi istruzione.
Peter Cordes

Mi piace la chiamata preservata. Ho aggiornato la risposta con lo stesso. Grazie per la recensione.
Jay Rajput
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.