¿Cuál es el propósito de los registros ESI y EDI?

119

¿Cuál es el propósito real y el uso de los registros EDI y ESI en ensamblador?

Sé que se utilizan para operaciones de cadenas para empezar.

¿Alguien también puede dar un ejemplo?

Tony el león
fuente
9
Vea esto: swansontec.com/sregisters.html
Jeffpowrs

Respuestas:

77

Hay algunas operaciones que solo puede hacer con DI / SI (o sus contrapartes extendidas, si no aprendió ASM en 1985). Entre estos se encuentran

REP STOSB
REP MOVSB
REP SCASB

Que son, respectivamente, operaciones de almacenamiento, carga y escaneo repetidos (= masivos). Lo que debe hacer es configurar SI y / o DI para que apunten a uno o ambos operandos, tal vez poner un recuento en CX y luego dejar que rip. Estas son operaciones que funcionan en un montón de bytes a la vez, y ponen la CPU en automático. Debido a que no está codificando bucles explícitamente, hacen lo suyo de manera más eficiente (generalmente) que un bucle codificado a mano.

Por si acaso se lo está preguntando: Dependiendo de cómo configure la operación, el almacenamiento repetido puede ser algo simple como ingresar el valor 0 en un gran bloque contiguo de memoria; MOVSB ​​se usa, creo, para copiar datos de un búfer (bueno, cualquier grupo de bytes) a otro; y SCASB se usa para buscar un byte que coincida con algún criterio de búsqueda (no estoy seguro de si solo está buscando en igualdad, o qué; puedes buscarlo :))

Eso es la mayor parte de lo que son esas reglas.

Carl Smotricz
fuente
7
Consejo de optimización del pasado: rep stosw es mucho más rápido que rep stosb , por lo que si copiar dos y dos bytes encaja con lo que está tratando de hacer, utilícelo en su código de ensamblaje x86 de 16 bits optimizado a mano ...
Alexander
88

SI= Índice de origen
DI= Índice de destino

Como han indicado otros, tienen usos especiales con las instrucciones de cadena. Para la programación en modo real, el ESregistro de segmento debe usarse con DIy DScon SIcomo en

movsb  es:di, ds:si

SI y DI también se pueden utilizar como registros de índice de propósito general. Por ejemplo, el Ccódigo fuente

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

se compila en

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

donde ebp+12contiene argv, ebxes jy editiene srcidx. Observe que la tercera instrucción usa edimultiplicado por 4 y agrega ebpdesplazamiento por 0x54 (la ubicación de srcp); los corchetes alrededor de la dirección indican indirección.


Aunque no recuerdo dónde lo vi, esto confirma la mayor parte, y esto (diapositiva 17) otros:

AX= acumulador = acumulador de
DXpalabra doble
CX= contador
BX= registro base

Parecen registros de propósito general, pero hay una serie de instrucciones que (¿inesperadamente?) Utilizan uno de ellos, ¿pero cuál? De forma implícita.

Wallyk
fuente
37

Códigos de operación como MOVSB ​​y MOVSW que copian de manera eficiente datos de la memoria apuntada por ESI a la memoria apuntada por EDI. Así,

mov esi, source_address
mov edi, destination_address
mov ecx, byte_count
cld
rep movsb ; fast!
comida de gato
fuente
12

Además de las operaciones de cadena (MOVS / INS / STOS / CMPS / SCASB / W / D / Q, etc.) mencionadas en las otras respuestas, quería agregar que también hay instrucciones de ensamblaje x86 más "modernas" que se usan implícitamente en menos EDI / RDI:

La instrucción SSE2 MASKMOVDQU(y la próxima AVX VMASKMOVDQU) escribe bytes de forma selectiva desde un registro XMM a la memoria apuntada por EDI / RDI.

PhiS
fuente
6

Además de los registros que se usan para operaciones masivas, son útiles por su propiedad de ser preservados a través de una llamada a función (llamada preservada) en la convención de llamadas de 32 bits. ESI, EDI, EBX, EBP, ESP se conservan en llamadas, mientras que EAX, ECX y EDX no se conservan en llamadas. Los registros de llamadas preservadas son respetados por la función de la biblioteca C y sus valores persisten a través de las llamadas a la función de la biblioteca C.

Jeff Duntemann en su libro de lenguaje ensamblador tiene un código ensamblador de ejemplo para imprimir los argumentos de la línea de comandos. El código usa esi y edi para almacenar contadores, ya que la función de biblioteca C printf no los modificará. Para otros registros como eax, ecx, edx, no hay garantía de que no sean utilizados por las funciones de la biblioteca C.

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

Consulte la sección 12.8 Cómo ve C los argumentos de la línea de comandos.

Tenga en cuenta que las convenciones de llamadas de 64 bits son diferentes de las convenciones de llamadas de 32 bits, y no estoy seguro de si estos registros se conservan en llamadas o no.

Jay Rajput
fuente
Nunca escuché "sagrado" usado para describir lo que la mayoría de la gente llama "volátil" / "no volátil", o "salvado de llamadas" versus "salvado de llamadas". Me gusta "call-preserve" / "call-clobbered", ya que no implica que se guarden en ningún lugar. De todos modos, ESI / RSI y EDI / RDI no se conservan en llamadas en el sistema V ABI x86-64.
Peter Cordes
Además, olvidó listar EBP y ESP como llamadas preservadas en las convenciones comunes de llamadas de 32 bits.
Peter Cordes
1
De todos modos, ese es un buen punto. En el código real, es más probable que elija EDI / ESI para algo basado en razones de convención de llamadas que porque sean especiales para cualquier instrucción.
Peter Cordes
Me gusta la llamada preservada. He actualizado la respuesta con lo mismo. Gracias por la reseña.
Jay Rajput