[successivo] [precedente] [inizio] [fine] [indice generale] [indice ridotto] [indice analitico] [home] [volume] [parte]


Capitolo 560.   Indirizzamento dei dati

In generale, con l'architettura x86 ci si preoccupa di definire il modo in cui fare riferimento ai dati nel sorgente in linguaggio assemblatore (incluso ciò che riguarda la pila), dal momento che per il riferimento alle istruzioni si usano etichette statiche che il compilatore traduce normalmente in indirizzi relativi (il «dislocamento»). Viene mostrata una tabella che riepiloga i vari modi con cui è possibile fare riferimento ai dati, secondo le due sintassi più comuni.

Tabella 560.1. Indirizzamento dei dati.

Esempio AT&T Esempio Intel Descrizione
$21
$0x15
$025
$0b10101
21
0x15
025
10101b
Si sta facendo riferimento al numero 2110 in modo letterale.
$nome_etichetta
nome_etichetta
Si fa riferimento all'indirizzo corrispondente all'etichetta, ovvero al numero che costituisce tale indirizzo.
nome_etichetta
[nome_etichetta]
Si fa riferimento all'area di memoria che inizia in corrispondenza dell'etichetta.
nome_etichetta±n
[nome_etichetta±n]
Si fa riferimento all'area di memoria che inizia in corrispondenza dell'etichetta, ±n byte.
%eax
eax
Si sta facendo riferimento al registro EAX, in qualità di variabile.
(%eax)
[eax]
Si sta facendo riferimento all'area di memoria che inizia a partire dall'indirizzo contenuto nel registro EAX
±n(%eax)
[eax±n]
Si sta facendo riferimento all'area di memoria che inizia a partire dall'indirizzo contenuto nel registro EAX, ±n byte.
nome_etichetta(%eax)
[eax+nome_etichetta]
Si sta facendo riferimento all'area di memoria che inizia a partire dall'indirizzo a cui fa riferimento l'etichetta, più il contenuto del registro EAX.
(nome_etichetta±n)(%eax)
[eax+nome_etichetta±n]
Si sta facendo riferimento all'area di memoria che inizia a partire dall'indirizzo a cui fa riferimento l'etichetta, più il contenuto del registro EAX, ±n byte.
(%eax,%ebx,n)
[eax+%ebx*n]
Si sta facendo riferimento all'area di memoria che inizia a partire da EAX+(EBX·n).
±m(%eax,%ebx,n)
[eax+%ebx*n±m]
Si sta facendo riferimento all'area di memoria che inizia a partire da (EAX+(EBX·n))±m.

560.1   Gestione di array

Per comprendere l'uso della forma più complessa di indirizzamento, si prenda l'esempio seguente, in cui appare un'etichetta, denominata record, che descrive una sequenza di valori, contenenti anche ciò che si vuole considerare una matrice di numeri.

#
.section .data
record:          .ascii "matrice"
                 .int    0,  1,  2,  3,  4,  5,  6,  7,  8,  9
                 .int   10, 11, 12, 13, 14, 15, 16, 17, 18, 19
                 .int   20, 21, 22, 23, 24, 25, 26, 27, 28, 29
                 .int   30, 31, 32, 33, 34, 35, 36, 37, 38, 39
                 .int   40, 41, 42, 43, 44, 45, 46, 47, 48, 49
                 .int   50, 51, 52, 53, 54, 55, 56, 57, 58, 59
                 .int   60, 61, 62, 63, 64, 65, 66, 67, 68, 69
                 .int   70, 71, 72, 73, 74, 75, 76, 77, 78, 79
                 .int   80, 81, 82, 83, 84, 85, 86, 87, 88, 89
                 .int   90, 91, 92, 93, 94, 95, 96, 97, 98, 99
dimensione_int:  .int    4      # 32 bit
dimensione_riga: .int   40      # 4 * 10 byte
riga:            .int    3      # da 0 a 9
colonna:         .int    5      # da 0 a 9
#
.section .text
.globl _start
#
_start:
    mov   riga, %eax                    # Legge le coordinate di riga e
    mov   colonna, %ecx                 # colonna, copiandole in EAX e ECX.
    mull  dimensione_riga               # EDX:EAX := EAX * 40.
    mov   (record+7)(%eax,%ecx,4), %ebx # EBX := array[riga,colonna].
bp1:
    mov   $1, %eax                      # Restituisce il valore trovato
    int   $0x80                         # nella matrice.
;
section .data
record:          db     "matrice"
                 dd      0,  1,  2,  3,  4,  5,  6,  7,  8,  9
                 dd     10, 11, 12, 13, 14, 15, 16, 17, 18, 19
                 dd     20, 21, 22, 23, 24, 25, 26, 27, 28, 29
                 dd     30, 31, 32, 33, 34, 35, 36, 37, 38, 39
                 dd     40, 41, 42, 43, 44, 45, 46, 47, 48, 49
                 dd     50, 51, 52, 53, 54, 55, 56, 57, 58, 59
                 dd     60, 61, 62, 63, 64, 65, 66, 67, 68, 69
                 dd     70, 71, 72, 73, 74, 75, 76, 77, 78, 79
                 dd     80, 81, 82, 83, 84, 85, 86, 87, 88, 89
                 dd     90, 91, 92, 93, 94, 95, 96, 97, 98, 99
dimensione_int:  dd      4      ; 32 bit
dimensione_riga: dd     40      ; 4 * 10 byte
riga:            dd      3      ; da 0 a 9
colonna:         dd      5      ; da 0 a 9
;
section .text
global _start
;
_start:
    mov   eax, [riga]                   ; Legge le coordinate di riga e
    mov   ecx, [colonna]                ; colonna, copiandole in EAX e ECX.
    mul   long [dimensione_riga]        ; EDX:EAX := EAX * 40.
    mov   ebx, [record+7+eax+ecx*4]     ; EBX := array[riga,colonna].
bp1:
    mov   eax, 1                        ; Restituisce il valore trovato
    int   0x80                          ; nella matrice.

In pratica, record individua l'inizio di una struttura composta da una stringa di sette byte, seguita da un centinaio di interi da 32 bit, suddivisi idealmente in righe da 10 unità. In pratica, una «riga» di questi numeri occupa 40 byte.

Per accedere a un certo elemento della matrice contenuta nel «record», occorre considerare uno scostamento iniziale di 7 byte, quindi occorre calcolare la posizione dell'elemento, secondo lo schema che si vede nella figura successiva.

matrice

Viene proposto un altro esempio equivalente, ma realizzato gestendo in modo diverso l'indirizzamento. La dichiarazione dei dati è la stessa:

...
_start:
    mov   riga, %eax                    # Legge le coordinate di riga.
    mull  dimensione_riga               # EDX:EAX := EAX * 40.
    mov   %eax, %ecx                    # ECX := riga * 40.
    #
    mov   colonna, %eax                 # Legge le coordinate di colonna.
    mull  dimensione_int                # EDX:EAX := EAX * 4.
    add   %eax, %ecx                    # ECX := (riga*40)+(colonna*4)
    #
    add   $7, %ecx                      # ECX := 7+(riga*40)+(colonna*4)
    mov   record(%ecx), %ebx            # EBX := array[riga,colonna].
bp1:
    mov   $1, %eax                      # Restituisce il valore trovato
    int   $0x80                         # nella matrice.
...
_start:
    mov   eax, [riga]                   ; Legge le coordinate di riga.
    mul   long [dimensione_riga]        ; EDX:EAX := EAX * 40.
    mov   ecx, eax                      ; ECX := riga * 40.
    ;
    mov   eax, [colonna]                ; Legge le coordinate di colonna.
    mul   long [dimensione_int]         ; EDX:EAX := EAX * 4.
    add   ecx, eax                      ; ECX := (riga*40)+(colonna*4)
    ;
    add   ecx, 7                        ; ECX := 7+(riga*40)+(colonna*4)
    mov   ebx, [record+ecx]             ; EBX := array[riga,colonna].
bp1:
    mov   eax, 1                        ; Restituisce il valore trovato
    int   0x80                          ; nella matrice.

Come si vede, si arriva a mettere nel registro ECX il risultato di 7+(riga×40)+(colonna×4); pertanto, alla fine si aggiunge solo l'indirizzo iniziale della struttura e si ottiene, complessivamente, l'indirizzo del valore cercato nella matrice.

Un altro esempio, dove si vede un altro modo di usare l'indirizzamento indiretto fornito dal linguaggio macchina:

...
_start:
    mov   riga, %eax                    # Legge le coordinate di riga.
    mull  dimensione_riga               # EDX:EAX := EAX * 40.
    mov   %eax, %ecx                    # ECX := riga * 40.
    #
    mov   colonna, %eax                 # Legge le coordinate di colonna.
    mull  dimensione_int                # EDX:EAX := EAX * 4.
    add   %eax, %ecx                    # ECX := (riga*40)+(colonna*4)
    #
    add   $7, %ecx                      # ECX := 7+(riga*40)+(colonna*4)
    mov   $record, %edx                 # EDX := indirizzo iniziale di "record".
    mov   (%edx,%ecx), %ebx             # EBX := array[riga,colonna].
bp1:
    mov   $1, %eax                      # Restituisce il valore trovato
    int   $0x80                         # nella matrice.
...
_start:
    mov   eax, [riga]                   ; Legge le coordinate di riga.
    mul   long [dimensione_riga]        ; EDX:EAX := EAX * 40.
    mov   ecx, eax                      ; ECX := riga * 40.
    ;
    mov   eax, [colonna]                ; Legge le coordinate di colonna.
    mul   long [dimensione_int]         ; EDX:EAX := EAX * 4.
    add   ecx, eax                      ; ECX := (riga*40)+(colonna*4)
    ;
    add   ecx, 7                        ; ECX := 7+(riga*40)+(colonna*4)
    mov   edx, record                   ; EDX := indirizzo iniziale di "record".
    mov   ebx, [edx+ecx]                ; EBX := array[riga,colonna].
bp1:
    mov   eax, 1                        ; Restituisce il valore trovato
    int   0x80                          ; nella matrice.

Infine, un esempio dove si fa in modo che ECX contenga l'indirizzo completo dell'elemento cercato:

...
_start:
    mov   riga, %eax                    # Legge le coordinate di riga.
    mull  dimensione_riga               # EDX:EAX := EAX * 40.
    mov   %eax, %ecx                    # ECX := riga * 40.
    #
    mov   colonna, %eax                 # Legge le coordinate di colonna.
    mull  dimensione_int                # EDX:EAX := EAX * 4.
    add   %eax, %ecx                    # ECX := (riga*40)+(colonna*4)
    #
    add   $7, %ecx                      # ECX := 7+(riga*40)+(colonna*4)
    add   $record, %ecx                 # ECX := indirizzo completo.
    mov   (%ecx), %ebx                  # EBX := array[riga,colonna].
bp1:
    mov   $1, %eax                      # Restituisce il valore trovato
    int   $0x80                         # nella matrice.
...
_start:
    mov   eax, [riga]                   ; Legge le coordinate di riga.
    mul   long [dimensione_riga]        ; EDX:EAX := EAX * 40.
    mov   ecx, eax                      ; ECX := riga * 40.
    ;
    mov   eax, [colonna]                ; Legge le coordinate di colonna.
    mul   long [dimensione_int]         ; EDX:EAX := EAX * 4.
    add   ecx, eax                      ; ECX := (riga*40)+(colonna*4)
    ;
    add   ecx, 7                        ; ECX := 7+(riga*40)+(colonna*4)
    add   ecx, record                   ; ECX := indirizzo completo.
    mov   ebx, [ecx]                    ; EBX := array[riga,colonna].
bp1:
    mov   eax, 1                        ; Restituisce il valore trovato
    int   0x80                          ; nella matrice.

560.2   Istruzione «LEA»

L'istruzione LEA consente di calcolare un indirizzo di memoria e di salvarlo in un registro. Per esempio, le due istruzioni successive, una con MOV e l'altra con LEA, fanno la stessa cosa:

    mov   (%ecx), %ebx
    lea   %ecx, %ebx

Ovvero:

    mov   ebx, [ecx]
    lea   ebx, ecx

Pertanto, con l'istruzione LEA, ciò che appare nell'operando che svolge il ruolo di «origine» viene considerato solo per il suo indirizzo e copiato nella destinazione. La differenza sostanziale, rispetto a MOV, sta nel poter usare le espressioni di indirizzamento indiretto. Per esempio, per riprendere l'esempio di questo capitolo, usato per mostrare come accedere a una matrice di numeri, si potrebbe fare una cosa come si vede nel listato successivo, anche se sarebbe poco utile in tale circostanza particolare:

...
_start:
    mov  riga, %eax                    # Legge le coordinate di riga e
    mov  colonna, %ecx                 # colonna, copiandole in EAX e ECX.
    #
    mull dimensione_riga               # EDX:EAX := EAX * 40.
    #
    lea  (record+7)(%eax,%ecx,4), %edx # EDX contiene l'indirizzo dell'elemento.
    mov  (%edx), %ebx                  # EBX := array[riga,colonna].
bp1:
    mov  $1, %eax                      # Restituisce il valore trovato
    int  $0x80                         # nella matrice.
...
_start:
    mov   eax, [riga]                  ; Legge le coordinate di riga e
    mov   ecx, [colonna]               ; colonna, copiandole in EAX e ECX.
    ;
    mul   long [dimensione_riga]       ; EDX:EAX := EAX * 40.
    ;
    lea   edx, [record+7+eax+ecx*4]    ; EDX contiene l'indirizzo dell'elemento.
    mov   ebx, [edx]                   ; EBX := array[riga,colonna].
bp1:
    mov   eax, 1                       ; Restituisce il valore trovato
    int   0x80                         ; nella matrice.

Appunti di informatica libera 2008 --- Copyright © 2000-2008 Daniele Giacomini -- <appunti2 (ad) gmail·com>


Dovrebbe essere possibile fare riferimento a questa pagina anche con il nome indirizzamento_dei_dati.htm

[successivo] [precedente] [inizio] [fine] [indice generale] [indice ridotto] [indice analitico] [home]

Valid ISO-HTML!

CSS validator!

Gjlg Metamotore e Web Directory