Assemblaggio - Modalità di indirizzamento

La maggior parte delle istruzioni in linguaggio assembly richiedono l'elaborazione di operandi. Un indirizzo operando fornisce la posizione in cui vengono memorizzati i dati da elaborare. Alcune istruzioni non richiedono un operando, mentre altre possono richiedere uno, due o tre operandi.

Quando un'istruzione richiede due operandi, il primo operando è generalmente la destinazione, che contiene dati in un registro o posizione di memoria e il secondo operando è la sorgente. La sorgente contiene i dati da consegnare (indirizzamento immediato) o l'indirizzo (nel registro o in memoria) dei dati. In genere, i dati di origine rimangono inalterati dopo l'operazione.

Le tre modalità di indirizzamento di base sono:

  • Registrare l'indirizzamento
  • Indirizzamento immediato
  • Indirizzamento della memoria

Registra indirizzamento

In questa modalità di indirizzamento, un registro contiene l'operando. A seconda dell'istruzione, il registro può essere il primo operando, il secondo operando o entrambi.

Per esempio,

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

Poiché l'elaborazione dei dati tra i registri non coinvolge la memoria, fornisce un'elaborazione più rapida dei dati.

Indirizzamento immediato

Un operando immediato ha un valore costante o un'espressione. Quando un'istruzione con due operandi utilizza l'indirizzamento immediato, il primo operando può essere un registro o una posizione di memoria e il secondo operando è una costante immediata. Il primo operando definisce la lunghezza dei dati.

Per esempio,

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

Indirizzamento diretto alla memoria

Quando gli operandi sono specificati nella modalità di indirizzamento della memoria, è richiesto l'accesso diretto alla memoria principale, solitamente al segmento di dati. Questo modo di affrontare si traduce in un'elaborazione più lenta dei dati. Per individuare la posizione esatta dei dati in memoria, abbiamo bisogno dell'indirizzo iniziale del segmento, che si trova in genere nel registro DS e un valore di offset. Questo valore di offset viene anche chiamatoeffective address.

Nella modalità di indirizzamento diretto, il valore di offset viene specificato direttamente come parte dell'istruzione, solitamente indicato dal nome della variabile. L'assemblatore calcola il valore di offset e mantiene una tabella dei simboli, che memorizza i valori di offset di tutte le variabili utilizzate nel programma.

Nell'indirizzamento diretto della memoria, uno degli operandi si riferisce a una posizione di memoria e l'altro operando fa riferimento a un registro.

Per esempio,

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

Indirizzamento con offset diretto

Questa modalità di indirizzamento utilizza gli operatori aritmetici per modificare un indirizzo. Ad esempio, guarda le seguenti definizioni che definiscono tabelle di dati:

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

Le seguenti operazioni accedono ai dati dalle tabelle in memoria nei registri:

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

Indirizzamento indiretto della memoria

Questa modalità di indirizzamento utilizza la capacità del computer di Segment: Offset addressing. In genere, a questo scopo vengono utilizzati i registri di base EBX, EBP (o BX, BP) e i registri di indice (DI, SI), codificati tra parentesi quadre per i riferimenti di memoria.

L'indirizzamento indiretto viene generalmente utilizzato per variabili contenenti diversi elementi come array. L'indirizzo iniziale dell'array è memorizzato, ad esempio, nel registro EBX.

Il frammento di codice seguente mostra come accedere a diversi elementi della variabile.

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

L'istruzione MOV

Abbiamo già utilizzato l'istruzione MOV utilizzata per spostare i dati da uno spazio di archiviazione a un altro. L'istruzione MOV accetta due operandi.

Sintassi

La sintassi dell'istruzione MOV è:

MOV  destination, source

L'istruzione MOV può avere una delle seguenti cinque forme:

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

Si prega di notare che -

  • Entrambi gli operandi nell'operazione MOV dovrebbero avere la stessa dimensione
  • Il valore dell'operando di origine rimane invariato

L'istruzione MOV a volte causa ambiguità. Ad esempio, guarda le dichiarazioni:

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

Non è chiaro se si desidera spostare un equivalente in byte o un equivalente in parola del numero 110. In tali casi, è consigliabile utilizzare un type specifier.

La tabella seguente mostra alcuni degli identificatori di tipo comuni:

Identificatore di tipo Byte indirizzati
BYTE 1
PAROLA 2
DWORD 4
QWORD 8
TBYTE 10

Esempio

Il seguente programma illustra alcuni dei concetti discussi sopra. Memorizza un nome "Zara Ali" nella sezione dati della memoria, quindi cambia il suo valore in un altro nome "Nuha Ali" a livello di programmazione e visualizza entrambi i nomi.

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 '

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

Zara Ali Nuha Ali