Assembly Programming Tutorial #1 – Introduzione

197 Views 0 Comment

Inizia una nuova serie di tutorial sul linguaggio ASSEMBLY riferito al processore INTEL 8086. Nei seguenti tutorial imparerai i basilari sulla programmazione assembly.

PROGRAMMAZIONE DI BASSO LIVELLO

Ogni calcolatore ha un livello ISA (Instruction Set Architecture) che comprende registri, istruzioni e caratteristiche di basso livello.

Vantaggi:

  • Performance molto più elevate rispetto ad altri linguaggi;
  • Programmi compatti;
  • Sfruttamento delle caratteristiche della macchina.

Svantaggi:

  • Programmi difficili da leggere e scrivere;
  • Facile commettere errori;
  • Impossibile scrivere grandi programmi.

LINGUAGGIO MACCHINA

In linguaggio macchina ogni istruzione corrisponde alla stringa di bit che verrà eseguita dalla CPU, è un linguaggio fortemente orientato alla macchina. Un’ istruzione in linguaggio macchina risulta direttamente ESEGUIBILE dalla CPU in quanto non ha bisogno di traduzioni, ma allo stesso tempo risulta ILLEGGIBILE all’ uomo.  Attualmente questo tipo di linguaggio è in disuso.

LINGUAGGIO ASSEMBLY

In linguaggio Assembly ogni istruzione è costituita da una stringa alfanumerica in corrispondenza 1 ad 1 con un’istruzione di linguaggio macchina. Un esempio di istruzione può essere MOV BH, 6

Il linguaggio assembly risulta maggiormente leggibile rispetto al linguaggio macchina, ma deve essere tradotto prima di essere eseguito. Attualmente il linguaggio asssembly viene adoperato per realizzare piccoli moduli altamente efficienti (sistemi operativi).

I REGISTRI

Nell’ 8086 sono presenti 4 Registri a 16 bit, ovvero i registri AX, BX, CX, DX.

AX: Accumulator
Viene usato per la computazione logico-aritmetica;
BX: Base
Stessi usi di AX
In alcuni casi può puntare alla memoria;
CX: Count
Registro usato come contatore
Viene decrementato automaticamente nei cicli quando si esegue l’istruzione LOOP;
DX: Data
Può contenere l’overflow di alcune operazioni aritmetiche.

I 4 registri d’uso generale possono essere considerati come 8 registri da 8 bit:

AX : AL, AH
BX: BL, BH
CX:  CL, CH
DX: DL, DH
I registri da 8 bit non sono indipendenti!

REGISTRI PUNTATORI ED INDICI

Sono inoltre presenti 4 registri da 16 bit, ovvero SP, BP, SI, DI

SP: Stack Pointer
Viene usato come puntatore allo stack e viene incrementato e decrementato dalle istruzioni POP E PUSH;
BP: Base Pointer
In genere punta a una locazione dello stack o alle variabili locali della procedura corrente;
SI: Source Index
Viene usato come puntatore per accedere alla memoria;
DI: Destination Index
Stesso uso di SI.

REGISTRO PUNTATORE DI ISTRUZIONE

Si tratta di un registro speciale a 16 bit denominato IP, il quale non viene utilizzato dalle istruzioni ma direttamente dalla CPU e contiene l’indirizzo dell’istruzione corrente e viene incrementato prima del completamento dell’istruzione in esecuzione.

IL REGISTRO DEI CODICI DI CONDIZIONE

E’ un Registro speciale a 16 bit che individua lo stato dell’ unità logico aritmetica (ALU) dopo l’esecuzione di ciascuna istruzione. Ogni bit (quasi) ha un significato specifico:
CF (Carry) Risultato con riporto;
ZF (Zero) Risultato nullo;
SF (Sign) Risultato negativo;
OF (Overflow) Overflow con segno;
PF (Parity) Risultato pari;
IF (Interrupt) CPU Interrompibile.

I REGISTRI DI SEGMENTO

Esistono altri 4 registri da 16 bit, ovvero CS, DS, SS, ES, usati come riferimento ai segmenti di memoria.
CS: Code Segment
Punta al segmento che contiene le istruzioni;
DS: Data Segment
Punta al segmento che contiene i dati;
SS: Stack Segment
Punta al segmento che contiene lo stack;
ES: Extra Segment
Punta al segmento extra (di riserva).

ORGANIZZAZIONE FISICA DELLA MEMORIA NELL’ 8086

La memoria può essere interpretata come un array di byte che inizia dalla prima cella (posizione 0) e finisce nell’ ultima (MaxRam)
Memory : array [0 … MaxRAM] byte;
Il valore indirizzabile in scrittura o lettura corrisponde all’indice dell’array.

Nel processore 8086 sono presenti registri a 16 bit, questo implica che la memoria indirizzabile(con indirizzamento lineare)sia di:

2^16 = 65536 = 64Kbyte
La segmentazione permette di estendere la memoria indirizzabile da
64Kbyte a 1Mbyte.

SEGMENTAZIONE DELLA MEMORIA

La segmentazione prevede l’uso di due componenti per specificare l’indirizzo di una locazione di memoria:

Un valore di segmento (segment)
Un valore di spostamento (offset) all’interno del segmento

La dimensione dell’offset limita la dimensione di un segmento e nell’ 8086 si hanno:

Offset da 16 bit -> un segmento non può superare 64Kbyte
Segment da 16 bit -> 65536 diversi segmenti
Per risalire all’ indirizzo fisico di una cella di memoria occorrerà convertire l’indirizzo segmentato.

Ogni registro di segmento punta alla base del proprio segmento:
00000h, 00010h, 00020h, …, 000F0h, 00100h, …, FFFF0h (indirizzi espressi in esadecimale)

Dato che i valori sono multipli di 16, l’ultima cifra saraà sempre zero e può essere eliminata nella rappresentazione dell’indirizzo.
Quindi si hanno 4 cifre esadecimali e di conseguenza 16 bit per ogni registro di segmento.
Per farla breve, un indirizzo fisico di memoria si calcola moltiplicando il valore del registro di segmento per 16 (10h) e sommando il valore dell’offset:

Es: segment:offset = 2000:2F00
si moltiplica 2000h × 10h = 20000h
si somma 20000h + 2F00h = 22F00h
2000:2F00 (indirizzo segmentato) ; 22F00h (indirizzo fisico)

LO STACK

Con il termine stack si indica un’area di memoria con una particolare organizzazione (stack = pila)

Lo stack comprende un insieme di locazioni di memoria in cui l’accesso è consentito solo all’ultimo dato immagazzinato, ovvero secondo l’ algoritmo LIFO (Last In First Out).
Quindi si può leggere un dato solo dall’ultima locazione scritta (TOP dello stack) e si può scrivere un dato solo nella locazione successiva al top dello stack.

REGISTRI PUNTATORI ALLO STACK

Il registro SS punta all’inizio del segmento dello stack;
Il registro SP punta al top dello stack;
Il registro BP punta alla base dello stack.

ISTRUZIONI PUSH E POP

L’operazione di PUSH permette di inserire una parola (due byte) in cima allo stack. Al termine della PUSH il registro SP viene decrementato di 2 (SP=SP-2)

L’operazione di POP permette di prelevare una parola dalla cima allo stack al termine della POP il registro SP è incrementato di 2 (SP=SP+2).

 

Nel prossimo articolo parleremo di Indirizzamento.

Stai cercando altre guide? Allora dai uno sguardo alla nostra raccolta dedicata alla Programmazione Assembly.

Alla prossima!


Continua a seguirci su:

Facebook Instagram Telegram Rss
0 Comments

Leave a Comment