Un par de preguntas sobre [base + índice*escala + disp] y AT&T disp(base, índice, escala)

Resuelto asked hace 9 años • 1 respuestas

La forma general para el direccionamiento de memoria en Intel y AT&T Syntax es la siguiente:

[base + index*scale + disp]      # Intel, including GAS .intel_syntax noprefix
disp(base, index, scale)         # AT&T

Mis preguntas son las siguientes:

  • ¿ Puede basey puede indexser cualquier registro?
  • ¿Qué valores pueden scaletomar? ¿Son 1, 2, 4 y 8 (siendo 1 el valor predeterminado)?
  • index¿ Son dispintercambiables (con la única diferencia de que indexes un registro y dispes un valor inmediato)?
 avatar Jan 14 '15 12:01
Aceptado

Esto se describe en el manual de Intel:

3.7.5 Especificación de un desplazamiento
La parte de desplazamiento de una dirección de memoria se puede especificar directamente como un valor estático (llamado desplazamiento) o mediante un cálculo de dirección compuesto por uno o más de los siguientes componentes:

  • Desplazamiento : un valor de 8, 16 o 32 bits.
  • Base : el valor en un registro de uso general.
  • Índice : el valor en un registro de uso general. [no puede ser ESP/RSP]
  • Factor de escala : un valor de 2, 4 u 8 que se multiplica por el valor del índice.

El desplazamiento que resulta de agregar estos componentes se llama dirección efectiva.

El factor de escala está codificado como un recuento de desplazamiento de 2 bits (0,1,2,3), para factores de escala de 1, 2, 4 u 8. Y sí, *1(recuento de desplazamiento = 0) es el valor predeterminado si escribir (%edi, %edx); eso es equivalente a(%edi, %edx, 1)


En la sintaxis de AT&T, las disp(base, index, scale)constantes van fuera de los pares. Algunos ensambladores de sintaxis Intel también permiten sintaxis como 1234[ebx], otros no. Pero la sintaxis de AT&T es rígida; cada componente del modo de direccionamiento sólo puede ir en su lugar apropiado. Por ejemplo:

movzwl  foo-0x10(,%edx,2), %eax

realiza una carga de 16 bits ("palabra") con extensión cero en EAX, desde la dirección foo-0x10 + edx*2. EDX es el registro índice, con factor de escala 2. No hay registro base. fooy -0x10ambos son parte del desplazamiento, ambos constantes de tiempo de enlace. fooes una dirección de símbolo que el vinculador completará y restará 0x10 (debido al -0x10desplazamiento del tiempo de ensamblaje).

Si tiene la opción, use solo una base en lugar de un índice con una escala de 1. Un índice requiere un byte SIB para codificarse, lo que hace que la instrucción sea más larga. Es por eso que los compiladores eligen modos de direccionamiento como 8(%ebp)acceder a la memoria de la pila, no 8(,%ebp).

Consulte también Hacer referencia al contenido de una ubicación de memoria. (modos de direccionamiento x86) para obtener más información sobre cuándo se puede utilizar una base, un índice y/o un desplazamiento.


Un desplazamiento de 16 bits solo se puede codificar en un modo de direccionamiento de 16 bits, que utiliza un formato diferente que no puede incluir un factor de escala y tiene una selección muy limitada de qué registros pueden ser una base o un índice.

Entonces, un modo como este 1234(%edx)tendría que codificar el 1234 como 32 bits disp32en código de máquina de 32 bits.

Los desplazamientos de bytes de -128 a +127 pueden utilizar una codificación corta de 8 bits. Su ensamblador se encargará de esto por usted, utilizando la codificación válida más corta para el desplazamiento.


Todo esto es idéntico en el modo de 64 bits para los modos de direccionamiento de 64 bits, y disp32 también se extiende por signo a 64 bits al igual que disp8.

El modo de 64 bits agrega un nuevo modo de direccionamiento diferente, symbol(%rip)que no funciona con ningún registro de propósito general, solo con un desplazamiento de 32 bits desde RIP. Consulte ¿Cómo funcionan las referencias de variables relativas a RIP como "[RIP + _a]" en la sintaxis Intel x86-64 GAS? que también cubre la sintaxis de AT&T.

Michael avatar Jan 14 '2015 06:01 Michael