Ensamblaje - Modos de direccionamiento

La mayoría de las instrucciones en lenguaje ensamblador requieren que se procesen operandos. Una dirección de operando proporciona la ubicación, donde se almacenan los datos a procesar. Algunas instrucciones no requieren un operando, mientras que otras instrucciones pueden requerir uno, dos o tres operandos.

Cuando una instrucción requiere dos operandos, el primer operando es generalmente el destino, que contiene datos en un registro o ubicación de memoria y el segundo operando es la fuente. La fuente contiene los datos que se van a entregar (direccionamiento inmediato) o la dirección (en el registro o en la memoria) de los datos. Generalmente, los datos de origen permanecen inalterados después de la operación.

Los tres modos básicos de direccionamiento son:

  • Registro de direcciones
  • Direccionamiento inmediato
  • Direccionamiento de memoria

Registro de direcciones

En este modo de direccionamiento, un registro contiene el operando. Dependiendo de la instrucción, el registro puede ser el primer operando, el segundo operando o ambos.

Por ejemplo,

MOV DX, TAX_RATE   ; Register in first operand
MOV COUNT, CX	   ; Register in second operand
MOV EAX, EBX	   ; Both the operands are in registers

Dado que el procesamiento de datos entre registros no implica memoria, proporciona un procesamiento de datos más rápido.

Direccionamiento inmediato

Un operando inmediato tiene un valor constante o una expresión. Cuando una instrucción con dos operandos usa direccionamiento inmediato, el primer operando puede ser un registro o ubicación de memoria, y el segundo operando es una constante inmediata. El primer operando define la longitud de los datos.

Por ejemplo,

BYTE_VALUE  DB  150    ; A byte value is defined
WORD_VALUE  DW  300    ; A word value is defined
ADD  BYTE_VALUE, 65    ; An immediate operand 65 is added
MOV  AX, 45H           ; Immediate constant 45H is transferred to AX

Direccionamiento de memoria directo

Cuando se especifican operandos en el modo de direccionamiento de memoria, se requiere acceso directo a la memoria principal, generalmente al segmento de datos. Esta forma de abordar da como resultado un procesamiento de datos más lento. Para localizar la ubicación exacta de los datos en la memoria, necesitamos la dirección de inicio del segmento, que normalmente se encuentra en el registro DS y un valor de compensación. Este valor de compensación también se llamaeffective address.

En el modo de direccionamiento directo, el valor de compensación se especifica directamente como parte de la instrucción, generalmente indicado por el nombre de la variable. El ensamblador calcula el valor de compensación y mantiene una tabla de símbolos, que almacena los valores de compensación de todas las variables utilizadas en el programa.

En el direccionamiento de memoria directo, uno de los operandos se refiere a una ubicación de memoria y el otro operando hace referencia a un registro.

Por ejemplo,

ADD	BYTE_VALUE, DL	; Adds the register in the memory location
MOV	BX, WORD_VALUE	; Operand from the memory is added to register

Direccionamiento de compensación directa

Este modo de direccionamiento utiliza los operadores aritméticos para modificar una dirección. Por ejemplo, observe las siguientes definiciones que definen tablas de datos:

BYTE_TABLE DB  14, 15, 22, 45      ; Tables of bytes
WORD_TABLE DW  134, 345, 564, 123  ; Tables of words

Las siguientes operaciones acceden a los datos de las tablas en la memoria en registros:

MOV CL, BYTE_TABLE[2]	; Gets the 3rd element of the BYTE_TABLE
MOV CL, BYTE_TABLE + 2	; Gets the 3rd element of the BYTE_TABLE
MOV CX, WORD_TABLE[3]	; Gets the 4th element of the WORD_TABLE
MOV CX, WORD_TABLE + 3	; Gets the 4th element of the WORD_TABLE

Direccionamiento de memoria indirecto

Este modo de direccionamiento utiliza la capacidad de la computadora de Segmento: direccionamiento de compensación . Generalmente, los registros base EBX, EBP (o BX, BP) y los registros de índice (DI, SI), codificados entre corchetes para referencias de memoria, se utilizan para este propósito.

El direccionamiento indirecto se usa generalmente para variables que contienen varios elementos como matrices. La dirección de inicio de la matriz se almacena, digamos, en el registro EBX.

El siguiente fragmento de código muestra cómo acceder a diferentes elementos de la variable.

MY_TABLE TIMES 10 DW 0  ; Allocates 10 words (2 bytes) each initialized to 0
MOV EBX, [MY_TABLE]     ; Effective Address of MY_TABLE in EBX
MOV [EBX], 110          ; MY_TABLE[0] = 110
ADD EBX, 2              ; EBX = EBX +2
MOV [EBX], 123          ; MY_TABLE[1] = 123

La instrucción MOV

Ya hemos utilizado la instrucción MOV que se utiliza para mover datos de un espacio de almacenamiento a otro. La instrucción MOV toma dos operandos.

Sintaxis

La sintaxis de la instrucción MOV es:

MOV  destination, source

La instrucción MOV puede tener una de las siguientes cinco formas:

MOV  register, register
MOV  register, immediate
MOV  memory, immediate
MOV  register, memory
MOV  memory, register

Tenga en cuenta que -

  • Ambos operandos en funcionamiento MOV deben ser del mismo tamaño
  • El valor del operando fuente permanece sin cambios

La instrucción MOV causa ambigüedad en ocasiones. Por ejemplo, mire las declaraciones:

MOV  EBX, [MY_TABLE]  ; Effective Address of MY_TABLE in EBX
MOV  [EBX], 110	      ; MY_TABLE[0] = 110

No está claro si desea mover un equivalente en bytes o un equivalente en palabra del número 110. En tales casos, es aconsejable utilizar un type specifier.

La siguiente tabla muestra algunos de los especificadores de tipo comunes:

Especificador de tipo Bytes dirigidos
BYTE 1
PALABRA 2
DWORD 4
QWORD 8
TBYTE 10

Ejemplo

El siguiente programa ilustra algunos de los conceptos discutidos anteriormente. Almacena un nombre 'Zara Ali' en la sección de datos de la memoria, luego cambia su valor a otro nombre 'Nuha Ali' mediante programación y muestra ambos nombres.

section	.text
   global _start     ;must be declared for linker (ld)
_start:             ;tell linker entry point
	
   ;writing the name 'Zara Ali'
   mov	edx,9       ;message length
   mov	ecx, name   ;message to write
   mov	ebx,1       ;file descriptor (stdout)
   mov	eax,4       ;system call number (sys_write)
   int	0x80        ;call kernel
	
   mov	[name],  dword 'Nuha'    ; Changed the name to Nuha Ali
	
   ;writing the name 'Nuha Ali'
   mov	edx,8       ;message length
   mov	ecx,name    ;message to write
   mov	ebx,1       ;file descriptor (stdout)
   mov	eax,4       ;system call number (sys_write)
   int	0x80        ;call kernel
	
   mov	eax,1       ;system call number (sys_exit)
   int	0x80        ;call kernel

section	.data
name db 'Zara Ali '

Cuando se compila y ejecuta el código anterior, produce el siguiente resultado:

Zara Ali Nuha Ali