vuoi
o PayPal
tutte le volte che vuoi
L'assembler è il programma che converte l'assembly in linguaggio macchina. L'assembly ha lo
scopo generale di consentire di ignorare il formato binario del linguaggio macchina: ogni codice
operativo viene sostituito da una sequenza di caratteri che lo rappresenta in forma mnemonica.
NASM (in tutte le distribuzioni Linux, Netwide ASseMbler)
Operandi:
Registro (add eax, ebx), memoria (indirizzo come offeset calcolato da registri o esplicito),
immediato (mov eax, 0034h), implicito (inc ecx)
Istruzione fondamentale: mov destinazione, origine (gli operando non possono essere entrambi
in memoria e devono avere la stessa lunghezza).
Istruzioni
mov eax, 3 (mette l'operando immediato 3 in eax)
mov bx, ax (mette il valore contenuto in ax nel registro bx)
add eax, 4 (eax incrementa di 4)
add al, ah (al diventa al+ah)
sub bx, 10 (decremento bx di 10)
Programmazione modulare
È un paradigma di programmazione che consiste nella realizzazione di programmi suddivisi in
moduli, ognuno dei quali svolge precise funzioni. L'obiettivo è quello di semplificare lo sviluppo, il
test e la manutenzione di programmi di grosse dimensioni.
Direttive
Non vengono tradotte in linguaggio macchina, servono all'assembler per: definire costanti,
definire quantità di memoria per memorizzare i dati, raggruppare memoria in segmenti, includere
condizionalmente pezzi di codice, includere altri files (programmazione modulare).
Ad es
%define DIMENSIONE 100
mov eax, DIMENSIONE
Direttive per i dati: servono per definire gli spazi di memoria necessari per i dati.
resX (serve per allocare spazi di memoria per dati non inizializzati), dX (serve per allocare spazi
di memoria per dati inizializzati), dove X sta per b(yte), w(ord), d(ouble word), q(uad word), t(en
bytes)
L1 db 0 ; (byte etichettato L1 valore iniziale 0)
L3 db 110101b ; (byte inizializzato al binario 110101)
L5 dd 1A92h ; (double word inizializzata all'esadecimale 1A92)
L6 resb 1 ; (byte non inizializzato)
Definizioni consecutive sono posizionate sequenzialmente in memoria
L9 db 0, 1, 2, 3 ; definisce 4 bytes
L10 db "p", "i", "p", "p", "o", 0 ; stringa C++ "pippo"
L11 db 'pippo', 0 ; stringa C++ "pippo"
Etichette
L indica l'indirizzo (offset) del dato
[L] indica il dato contenuto in memoria a quell'indirizzo
Ad es
mov al, [L1] ; copia in AL il byte all'indirizzo L1
NASM non controlla il tipo dei dati!
mov [L6], 1 ; mette 1 ad L6 (ERROR! Operation size not specified)
Ma mov dword [L6], 1 ; ok
Stack
Porzione di memoria (locazioni contigue) usata per memorizzare i dati dal programma in
esecuzione. Ha una struttura LIFO (Last in First Out): l'ultimo dato immesso sarà poi il primo ad
essere preso. Anche le chiamate ai sottoprogrammi vengono gestite con disciplina LIFO.
Se eseguissi
PUSH EAX
PUSH EBX
e poi richiamo nei registri i loro rispettivi valori così
POP EAX
POP EBX
Avrei messo in EAX il valore prima contenuto in EBX, in EBX il valore prima contenuto in EAX,
invertendo il tutto.
La sequenza corretta di passaggi è:
PUSH EAX
PUSH EBX
POP EBX
POP EAX
Sottoprogrammi (subroutines)
In un linguaggio procedurale, un programma è una sequenza di istruzioni o sentenze. Mentre ciò
rimaneva comodo per programmi di piccole dimensioni, risultava invece scomodo per
programmi composti da tante righe di codice e molte istruzioni. Per questo si pensò di dividere i