tutorial assembler assembly x86 nasm yasm

assembly - assembler - Uso básico de inmediates(corchetes) en ensamblaje x86 y yasm



nasm tutorial (4)

Supongamos que tengo lo siguiente declarado:

section .bss buffer resb 1

Y estas instrucciones siguen:

mov al, 5 mov [buffer], al mov bl, [buffer] mov cl, buffer

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

Estoy confundido acerca de las diferencias entre

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

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

Suponga que el array resb 0 declaración array resb 0 existe en la section .bss . Mi entendimiento es que:

  • mov edi, array pone la dirección de memoria del índice zeroth array en edi .
  • mov [edi], 3 coloca el VALOR 3 en el índice zeroth de la matriz
  • después de add edi, 3 , edi ahora contiene la dirección de memoria del tercer índice de la matriz
  • mov al, [array] pone los datos en el índice zeroth en al .
  • mov al, [array+3] coloca los DATOS en el tercer índice en al .
  • mov [al], [array] no es válido, por el motivo que sea.
  • mov array, 3 no es válido, porque no se puede decir "Oye, no me gusta el desplazamiento en el que se almacena la array , así que lo llamaré 3"
  • mov [array], 3 coloca el valor 3 en el índice zeroth de la matriz.

Por favor mencione si alguno de estos es falso.


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:

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

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

  • También puede usar direccionamiento indirecto como mov reg2,[reg1] proporcionó puntos reg1 a una ubicación válida, y transferirá el valor apuntado por reg1 a reg2.

Entonces, mov cl, buffer moverá la dirección del buffer a cl (que puede o no dar la dirección correcta, ya que cl tiene solo un byte de longitud), mientras que mov cl, [buffer] obtendrá el valor real.

Resumen

  • Cuando usa [a], se refiere al valor en el lugar donde señala. Por ejemplo, si a es F5B1 , entonces [a] se refiere a la dirección F5B1 en RAM .
  • Las etiquetas son direcciones, es decir, valores como F5B1 .
  • Los valores almacenados en los registros no tienen que ser referenciados como [reg] porque los registros no tienen direcciones. De hecho, los registros pueden considerarse como valores inmediatos.

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

  1. Las direcciones pueden ser mayores que 8 bits ( cl es de 8 bits, cx es de 16 bits, ecx es de 32 bits, rcx es de 64 bits). Entonces, es probable que cl sea ​​igual a la dirección del buffer variable. Solo tendrá los 8 bits menos significativos de la dirección.
  2. Si hay rutinas de interrupción o subprocesos que pueden anticiparse al código anterior y / o acceder al buffer , el valor en bl puede diferir de 5. Las rutinas de interrupción interrumpidas pueden afectar cualquier registro cuando no conservan los valores de registro.

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

Entonces, algo como

mov REG, x

mueve el valor de x a REG , mientras que

mov REG, [x]

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

En cuanto a tu pregunta:

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

Sí, estás en lo correcto. Pero tenga en cuenta que, dado que CL tiene solo 8 bits de ancho, solo contendrá el byte menos significativo de la dirección del buffer .


Para todas las instrucciones con el uso de valores inmediatos como un operando para escribir el valor en una ubicación de ram (o para calcular dentro), tenemos que especificar a cuántos bytes queremos acceder. Debido a que nuestro ensamblado no puede saber si solo queremos acceder a un byte , una palabra o un doppleword, por ejemplo, si el valor inmediato es un valor menor, como se muestra en 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