Uso básico de inmediatos frente a corchetes en el ensamblaje YASM/NASM x86

Resuelto InvalidBrainException asked hace 12 años • 4 respuestas

Supongamos que tengo lo siguiente declarado:

section .bss
buffer    resb     1

Y estas instrucciones siguen en section .text:

mov    al, 5                    ; mov-immediate
mov    [buffer], al             ; store
mov    bl, [buffer]             ; load
mov    cl, buffer               ; mov-immediate?

¿Estoy en lo cierto al entender que bl contendrá el valor 5 y cl contendrá la dirección de memoria de la variable?buffer ?

Estoy confundido acerca de las diferencias entre

  • mover un inmediato a un registro,
  • mover un registro a un inmediato (¿qué entra, los datos o la dirección?) y
  • mover un inmediato a un registro sin los corchetes
    • Por ejemplo, mov cl, bufferfrente amov cl, [buffer]

ACTUALIZACIÓN: Después de leer las respuestas, supongo que el siguiente resumen es exacto:

  • mov edi, arraycoloca la dirección de memoria del índice de matriz cero en edi. es decir, la dirección de la etiqueta.
  • mov byte [edi], 3pone el VALOR 3 en el índice cero de la matriz
  • después add edi, 3, ediahora contiene la dirección de memoria del tercer índice de la matriz
  • mov al, [array]carga los DATOS en el índice cero en al.
  • mov al, [array+3]carga los DATOS en el tercer índice en al.
  • mov [al], [array]no es válido porque x86 no puede codificar 2 operandos de memoria explícitos y porque alsolo tiene 8 bits y no se puede usar ni siquiera en un modo de direccionamiento de 16 bits. Hacer referencia al contenido de una ubicación de memoria. (modos de direccionamiento x86)
  • mov array, 3no es válido porque no puedes decir "Oye, no me gusta el desplazamiento en el que arrayestá almacenado, así que lo llamaré 3". Un inmediato sólo puede ser un operando fuente.
  • mov byte [array], 3coloca el valor 3 en el índice cero (primer byte) de la matriz. El byteespecificador es necesario para evitar ambigüedad entre byte/palabra/dword para instrucciones con memoria y operandos inmediatos. De lo contrario, sería un error en tiempo de ensamblaje (tamaño de operando ambiguo).

Por favor mencione si alguno de estos es falso. (nota del editor: arreglé errores/ambigüedades de sintaxis para que los válidos sean en realidad sintaxis NASM válida. Y vinculé otras preguntas y respuestas para obtener más detalles)

InvalidBrainException avatar Apr 28 '12 17:04 InvalidBrainException
Aceptado

Los corchetes funcionan esencialmente como un operador de desreferencia (por ejemplo, como *en C).

Entonces, algo como

mov REG, x

mueve el valor de xhacia REG, mientras que

mov REG, [x]

mueve el valor de la ubicación de memoria a la que xapunta hacia REG. Tenga en cuenta que si xes una etiqueta, su valor es la dirección de esa etiqueta.

En cuanto a tu pregunta:

¿Estoy en lo cierto al entender que bl contendrá el valor 5 y cl contendrá la dirección de memoria del búfer variable?

Sí, estás en lo correcto. Pero ojo que, al CLtener sólo 8 bits de ancho, sólo contendrá el byte menos significativo de la dirección del buffer.

mtvec avatar Apr 28 '2012 10:04 mtvec

De hecho, su pensamiento es correcto. Es decir, bl contendrá 5 y cl la dirección de memoria del búfer (de hecho, el búfer de etiquetas es una dirección de memoria en sí).


Ahora, déjame explicarte las diferencias entre las operaciones que mencionaste:

  • Se puede mover un elemento inmediato a un registro usando mov reg,imm. Lo que puede resultar confuso es que las etiquetas, por ejemplo, el búfer, son valores inmediatos que contienen una dirección.

  • Realmente no puedes mover un registro a un inmediato, ya que los valores inmediatos son constantes, como 2o FF1Ah. Lo que puedes hacer es mover un registro al lugar donde apunta la constante. Puedes hacerlo como mov [const], reg.

  • También puede utilizar el direccionamiento indirecto, como mov reg2,[reg1]los puntos reg1 proporcionados a una ubicación válida, y transferirá el valor señalado por reg1 a reg2.


Por lo tanto, mov cl, buffermoverá la dirección del búfer a cl (que puede dar o no la dirección correcta, ya que cl tiene solo un byte de longitud), mientras que mov cl, [buffer]obtendrá el valor real.

Resumen

  • Cuando usas [a], entonces te refieres al valor en el lugar al que apunta a. Por ejemplo, si a es F5B1, entonces [a] se refiere a la dirección F5B1 en la RAM .
  • Las etiquetas son direcciones, es decir, valores como F5B1.
  • No es necesario hacer referencia a los valores almacenados en registros como [reg] porque los registros no tienen direcciones. De hecho, los registros pueden considerarse como valores inmediatos.
byrondrossos avatar Apr 28 '2012 10:04 byrondrossos

Estás entendiendo la idea. Sin embargo, hay algunos detalles que vale la pena tener en cuenta:

  1. Las direcciones pueden, y generalmente son, mayores de lo que pueden contener 8 bits ( clson 8 bits, cxson 16 bits, ecxson 32 bits, rcxson 64 bits). Por lo tanto, cles probable que no sea igual a la dirección de la variable buffer. Sólo tendrá los 8 bits menos significativos de la dirección.
  2. Si hay rutinas de interrupción o subprocesos que pueden adelantarse al código y/o acceso anterior buffer, el valor en blpuede diferir de 5. Las rutinas de interrupción rotas pueden afectar a cualquier registro cuando no preservan los valores de los registros.
Alexey Frunze avatar Apr 28 '2012 10:04 Alexey Frunze

Para todas las instrucciones que utilizan valores inmediatos como operandos para escribir el valor en una ubicación de RAM (o para calcular dentro), tenemos que especificar a cuántos bytes queremos acceder. Porque nuestro ensamblado no puede saber si queremos acceder solo a un byte , una palabra o una doble palabra , por ejemplo si el valor inmediato es un valor menor, como lo muestran las siguientes instrucciones.

array db 0FFh, 0FFh, 0FFh, 0FFh
mov byte [array], 3

resultados:

array db 03h, 0FFh, 0FFh, 0FFh

....

mov word [array], 3

resultados:

array db 03h, 00h, 0FFh, 0FFh

....

mov dword [array], 3

resultados:

array db 03h, 00h, 00h, 00h

Puñal

Dirk Wolfgang Glomp avatar May 05 '2013 12:05 Dirk Wolfgang Glomp