Default.asm

    .MODEL small    ; specifica il modello di memoria
    .STACK          ; riserva spazio per lo stack (default = 1 Kbyte)
    .DATA           ; crea un segmento di dati (di tipo NEAR)

;-------------------------------------------------------------------
; definizione variabili

;-------------------------------------------------------------------
    .CODE          ; definisce un segmento di codice
    .STARTUP       ; genera le istruzioni di interfaccia a MS-DOS

;-------------------------------------------------------------------
; definizione codice main

;-------------------------------------------------------------------

    .EXIT          ; genera le istruzioni di ritorno a MS-DOS

;-------------------------------------------------------------------
; definizione codice procedure

;-------------------------------------------------------------------

    END            ; fine del modulo da assemblare
Formato istruzioni nel codice sorgente
label:   mnemonico   operando, operando   ;commento

Variabili

Identificano in modo simbolico una zona di memoria contenente dati.
All’atto della definizione della variabile, si definiscono
Pseduo-istruzioni per la Definizione di Variabili
simbolo direttiva espressione
direttive: BYTE (DB), WORD (DW), DWORD (DD), QWORD (DQ)

valore: valore numerico, stringa tra apici, il carattere ?, il costrutto num DUP (val) che repplica num volte il valore val

Costanti

Pseduo-istruzioni per la Definizione di Costanti
simbolo EQU espressione
simbolo = espressione
Definiscono costanti simboliche durante l’assemblaggio. Le costanti definite con = possono essere cambiate di valore nel corso del programma, a differenza di quelle definite con EQU.

Modi di indirizzamento

1) Register Addressing

Nell'istr è specificato il nome del registro da utilizzare come operando.

2) Immediate Addressing

Nell'istr stessa è specificato come operando un valore immediato

3) Direct Addressing

Nell'istr è contenuto l'identificatore di una variabile, corrispondente all'effective address della parola di memoria da utilizzare come operando. Alla variabile può essere sommato o sottratto un dispacement

4) Register Indirect

L'effettive address di una variabile è contenuto in uno dei registri: Base Register (BX), Index Register (DI oppure SI), Base Pointer (BP). Nell'istruzione viene quindi indicato non il valore della variabile ma l'indirizzo in cui si trova: il reindirizzamento avviene attraverso la notazione: [BX]

5) Base Relative

6) Direct Indexed

7) Base Indexed

Operatori

Operatori per il calcolo degli attributi di una variabile

OFFSET

OFFSET variabile
Restituisce il il valore dell'offset di una variabile. (in alternativa alla funzione LEA). E' utilizzabile solo su operandi indirizzati direttamente attraverso un nome di variabile e nn ad operandi indirizzati indirettamente.

TYPE

TYPE variabile
Restituisce il numero di byte dell'operando.

LENGTH

LENGTH variabile
Restituisce in numero di unità allocate per l'operando. Ha senso solo per variabili allocate con l'operando DUP

SIZE

SIZE variabile
Restituisce lo spazio di memoria utilizzato dall'operando. (SIZE = LENGTH * TYPE)

SEG

SEG variabile
Restituisce l'adr di inizio del segmento a cui appartiene l'operando variabile.

Operatori che modificano il tipo di una variabile

PTR

tipo PTR variabile
Forza l'assemblatore a modificare per l'istruzione corrente il tipo del dato avente come identificatore nome.

Operatori aritmetici, logici e relazionali

MOV

MOV < registro|memoria > , < registro|memoria|valore imm. >

I dati vengono letti dall’operando sorgente e memorizzati nell’operando destinazione.

XCHG

XCHG < registro|memoria > , < registro|memoria >
Esegue lo scambio tra due registri o tra un registro ed una locazione di memoria.
Gli operandi devono essere dello stesso tipo

LEA

LDS

LES

PUSH e POP

PUSH < registro|memoria >
POP  < registro|memoria >
PUSH: trasferisce una word dall'operando sorgente all'elemento dello stack indirizzato da SP che viene incrementato di 2.
POP:   trasferisce una word dall'elemento dello stack indirizzato da SP all'operando destinazione e decrementa SP di 2.
PUSHA
POPA
Eseguono le operazioni di push e pop di tutti i registri general purpose (AX, BX, CX, DX, SP, BP, SI, DI)
NB: il valore del registro SP caricato nello stack è pari al valore che tale registro assume prima del caricamento del primo registro.
PUSHF
POPF
Permettono di salvare e di ripristinare i 16 bit della parola di stato (PSW)

SAHF LAHF

SAHF
LAHF
Permettono di accedere al valore dei flag memorizzandoli e prelevandoli dal registro AH.
LAHF: trasferisce i valori dei flag SP, ZF, AF, e CF nel registro AH
SAHF: trasferisce i valori di alcuni bit del registro AH nei flag SF, ZF, AF e CF.

ADD

ADD < registro|memoria > , < registro|memoria|valore imm. >
Esegue un’addizione tra l’operando dest e l’operando sorg e scrive il risultato nell’operando dest; l’operando sorg rimane immutato.
Modifica il valore di tutti i flag (AF, PF, CF, SF, OF, ZF).
Gli operandi devono essere dello stesso tipo.

ADC

ADC < registro|memoria > , < registro|memoria|valore imm. >
Somma al contenuto dell’operando dest il contenuto dell’operando sorg ed il valore del flag CF.
NB: Somma tra numeri interi su 32 bit
Per eseguire le operazioni aritmetiche di somma tra numeri di tipo doubleword occorre sommare coppie di word, cominciando da quella meno significativa: si sommano le due word meno significative utilizzando l’istruzione ADD, quindi si sommano le due word più significative utilizzando l’istruzione ADC.

SUB

SUB < registro|memoria > , < registro|memoria|valore imm. >
Esegue una sottrazione tra l’operando dest e l’operando sorg e scrive il risultato nell’operando dest; l’operando sorg rimane immutato.
Modifica il valore di tutti i flag (AF, PF, CF, SF, OF, ZF).
Gli operandi devono essere dello stesso tipo.

SBB

SBB < registro|memoria > , < registro|memoria|valore imm. >
Esegue la sottrazione tra l’operando dest e l’operando sorg; il valore del flag CF viene sottratto al risultato ed il valore ottenuto viene copiato nell’operando dest; l’operando sorg rimane immutato.

INC e DEC

INC < registro|memoria >
DEC < registro|memoria >
L’istruzione INC incrementa operando di un’unità e copia il risultato in operando stesso.
L’istruzione DEC decrementa operando di un’unità e copia il risultato in operando stesso.
Le due istruzioni aggiornano tutti i flag di stato tranne il flag CF.

CBW

CBW
Converte un byte nella word equivalente. (Caricare byte in AL, conversione a word in AX)
Utile quando si vuole eseguire un’operazione di addizione o sottrazione tra un numero memorizzato in un byte ed un numero memorizzato in una word.

CWD

CWD
Converte una word nella double word equivalente. (Caricare word in AX, conversione in double word in DX:AX)
Utile quando si vuole eseguire un'operazione di divisione tra due numeri a 16 bit.

NEG

NEG < registro|memoria >
Cambia il segno di operando, che si assume rappresentato in complemento a 2.
L’istruzione NEG aggiorna lo stato di tutti i flag di stato.

MUL e IMUL

MUL     < registro|memoria >
IMUL < registro|memoria >
Permettono di eseguire l’operazione di moltiplicazione tra numeri interi senza segno (MUL) e con segno (IMUL). I fattori della moltiplicazione devono essere dello stesso tipo.
L'operando specificato nella MUL (o nella IMUL) verra moltiplicato per il numero che è contenuto nell'accumulatore (AX per i 16bit, AL per gli 8bit o EAX per i 32bit).
Il risultato dipende dagli operandi:
1byte * AL     risultato in AX (CF=0 e OF=0 se e solo se AH=0)
2byte * AX     risultato in DX:AX (CF=0 e OF=0 se e solo se DX=0)
4byte * EAX   risultato in EDX:EAX (CF=0 e OF=0 se e solo se EDX=0)

DIV e IDIV

DIV     < registro|memoria >
IDIV < registro|memoria >
Permettono di eseguire l'operazione di divisione tra numeri interi senza segno (DIV) e con segno (IDIV).
Divisione 16bit / 8bit: dividendo in AX, divisore specificato nell'operando. Risultato divisione in AL, resto in AH.   NB il dividendo viene perso!
Divisione 32bit / 16bit: dividendo in DX:AX, divisore specificato nell'operando (no reg AX o DX). Risultato in AX e resto in DX.
Divisione 16bit / 16bit: si deve convertire con CWD il dividendo espandendolo a 32bit.

Istruzioni di salto

JMP

JMP < registro|memoria >
Salto incondizionato all'istruzione specificata in destinazione (label)

CMP

CMP < registro|memoria > , < registro|memoria >
Esegue il confronto tra l'operando destinazione e l'operando sorgente. (esegue la sottrazione tra l'operando destinazione e l'operando sorgente, senza restituire il risultato). Aggiorna opportunamente tutti i flag di stato.

JXXX

JXXX < registro|memoria >
XXX è un suffisso ke specifica le condizioni dei flag
Confronto tra numeri con segno
Confronto tra numeri senza segno
JL
JB
dest    <      sorg
JLE
JA
dest    <=    sorg
JG
JBE
dest    >      sorg
JGE
JAE
dest    >=    sorg
JE
JE
dest    ==    sorg
JNE
JNE
dest    <>    sorg

JZ
ZF = 1
JNZ
ZF = 0
JS
SF = 1
JNS
SF = 0
JO
OF = 1
JNO
OF = 0
JC
CF = 1
JNC
CF = 0
JP
PF = 1
JNP
PF = 0


Procedure

Il massimo livello di annidamento delle procedura è limitato dalle dimensioni dello stack.

Definizione di procedure

La definizione di una procedura comincia e termina con una direttiva. Vanno dichiarate alla fine del programma
< nome_procedura > PROC < NEAR | FAR > ; se il tipo viene omesso viene assunto NEAR di default
                  
                   ; corpo della procedura

< nome_procedura > ENDP
Una procedura è di tipo NEAR se è richiamabile solo all'interno dello stesso segmento di codice, mentre una procedura di tipo FAR può essere chiamata da procedure appartenenti a segmenti di codice diversi.
NB occorre fare in modo che ogni procedura esegua come prima operazione il salvataggio nello stack di tutti i registri ke vengono da essa modificati. E prevederne un ripristino al termine della procedura. Essendo lo stack una coda di tipo LIFO l'ordine delle istr POP deve essere l'inverso di quello delle istr PUSH.

Gestione di una procedura

Chiamata di una procedura

CALL < nome_procedura >
Trasferisce il controlle del flusso del programma alla procedura nome_procedura.
L'istr CALL salva nello stack il valore del registro IP (eventualmente anche di CS per le procedure di tipo FAR) per poter riprendere l'esecuzione della procedura chiamante con l'istr successiva a quella di chiamata terminata la procedura. Pone quindi in IP l’indirizzo specificato da nome_procedura, che rappresenta l’adr della prima istr della procedura. Salta all’indirizzo specificato da IP

Ritorno di una procedura

RET < pop_value > ; pop_value optional
Permette di restituire il controllo alla procedura chiamante, una volta che la procedura chiamata ha terminato l'esecuzione. Sempre presente al termine di una procedura.
L'operando pop_value è opzionale e corrisponde ad un valore immediato; esso permette di eseguire l'operazione di liberazione dello stack al momento del ritorno alla procedura chiamata di un numero di byte pari a pop_value.
L'istr RET recupera dallo stack il valore dell’indirizzo di ritorna e lo copia in IP (assumento che l'adr di ritorno sia in cima allo stack). Estrazione dallo stack di pop_value byte. Salta quindi al'adr specificato da IP.

Passaggio di parametri

La procedura chiamante può passare in entrata alla procedura chiamata alcuni valori, detti parametri. La procedura chiamata può passare in uscita alcuni parametri alla procedura chiamante.
Esistono diverse modalità di passaggio di parametri:
- Tramite registri (Veloce, Limitato)
- Tramite stack (Più lento (accesso alla memoria), Più generale)
I possibili metodi con cui i parametri vengono trasferiti alle procedure si caratterizzano in due categorie fondamentali:
- Trasferimento per valore (by value): la procedura chiamante passa a quella chiamata una copia del valore del parametro. La procedura chiamante non vede le modifiche effettuate sul parametro
dalla procedura chiamata, in quanto le modifiche compiute da questa avvengono esclusivamene sulla copia.
- Trasferimento per riferimento (by reference): la procedura chiamante passa alla procedura chiamata l’indirizzo di memoria del parametro: ogni modifica del parametro effettuata dalla procedura chiamata si ripercuote sul valore del parametro per la procedura chiamante.