Algoritmi, Programmi e Classificazione dei Linguaggi

// obiettivi di apprendimento
Distinguere algoritmo e programma
Classificare i linguaggi di programmazione per livello di astrazione
Comprendere le differenze tra linguaggi di alto e basso livello
Collegare il concetto di linguaggio all’architettura hardware
📄
Slides
Algoritmi e Linguaggi di Programmazione

Algoritmo e programma — due concetti distinti

Prima di scrivere qualsiasi codice è fondamentale distinguere due concetti che spesso vengono confusi.

ALGORITMO
Una sequenza finita di istruzioni per risolvere un problema — indipendente dal linguaggio e dall’hardware.
Descrive il cosa fare
PROGRAMMA
L’implementazione dell’algoritmo in un linguaggio eseguibile — dipende dalla piattaforma e dall’architettura.
Descrive il come farlo in un contesto specifico

Esempio — somma di due numeri

Lo stesso problema espresso prima come algoritmo in pseudocodice, poi come programma Assembly:

// algoritmo — pseudocodice
Leggi a
Leggi b
Somma = a + b
Stampa Somma
// programma — Assembly 8086
MOV AX, a      ; carica a in AX
ADD AX, b      ; somma b ad AX
MOV somma, AX  ; salva il risultato
// punto chiave
Lo stesso algoritmo può essere implementato in Python, C, Java o Assembly — la logica non cambia. Ciò che cambia è quanto il programmatore deve conoscere dell’hardware sottostante.

Classificazione dei linguaggi di programmazione

I linguaggi di programmazione si classificano in base al livello di astrazione rispetto all’hardware. Più il linguaggio è ad alto livello, più si avvicina al linguaggio naturale e si allontana dalla macchina — e viceversa.

ALTO LIVELLO
Indipendente dall’hardware — vicino al linguaggio naturale
Python, C, Java, JS
BASSO LIVELLO
Dipendente dall’architettura — accesso diretto all’hardware
Assembly x86, ARM ASM
LINGUAGGIO MACCHINA
Binario puro — eseguito direttamente dalla CPU
10110000 01100001

Linguaggi di alto livello

I linguaggi di alto livello sono indipendenti dall’hardware e più vicini al modo in cui gli esseri umani ragionano. Il programmatore si concentra sulla logica del problema senza preoccuparsi di registri, indirizzi o dimensioni dei dati.

# Python — alto livello
x = 5 + 3
print(x)    # Output: 8
// vantaggi
Codice leggibile e manutenibile
Portabile su architetture diverse
Sviluppo più rapido
// limiti
Nessun controllo diretto sull’hardware
Overhead introdotto dalla traduzione
Meno efficiente in scenari critici

Linguaggi di basso livello — Assembly

I linguaggi di basso livello sono strettamente dipendenti dall’architettura hardware. Il programmatore interagisce direttamente con registri, indirizzi di memoria e dimensioni dei dati — nulla è gestito automaticamente.

; Assembly 8086 — basso livello
MOV AL, 05h    ; carica il valore 5 nel registro AL
ADD AL, 03h    ; somma 3 ad AL → AL = 8

Per scrivere questo codice il programmatore deve conoscere esplicitamente:

REGISTRI
Quale registro usare per quale operazione — AX, BX, AL, AH
DIMENSIONE DATI
Byte (8 bit) o word (16 bit) — uso di AL vs AX non è intercambiabile
INDIRIZZAMENTO
Come accedere alla memoria — diretto, indiretto, tramite registro base…
// dipendenza dall’architettura
Un programma Assembly scritto per l’8086 non è eseguibile su architetture diverse senza adattamenti. Ogni famiglia di processori (x86, ARM, RISC-V) ha il proprio set di istruzioni, i propri registri e le proprie convenzioni — rendendo il codice Assembly non portabile.

Confronto diretto — alto livello vs basso livello

La stessa operazione somma 5 + 3 a confronto sui tre livelli:

LivelloCodiceCosa gestisce il programmatorePortabilità
Alto livellox = 5 + 3Solo la logicaQualsiasi architettura
AssemblyMOV AL, 05h
ADD AL, 03h
Registri, dimensioni, indirizzamentoSolo architettura specifica
Macchina10110000 00000101Tutto — bit per bitSolo CPU specifica

Linguaggio macchina e Assembly — il rapporto

Il linguaggio macchina è l’unico formato eseguibile direttamente dalla CPU — pura sequenza di bit. L’Assembly è la sua rappresentazione simbolica leggibile dall’uomo: ogni mnemonico (MOV, ADD, JMP) corrisponde a una specifica sequenza binaria definita dall’ISA.

; Assembly → codice macchina (corrispondenza diretta)

MOV AL, 05h   →   10110000 00000101
                   │opcode│  │operando│

ADD AL, 03h   →   00000100 00000011
                   │opcode│  │operando│
// perché studiare Assembly sull’8086
L’8086 è il modello didattico ideale: architettura semplice, ISA ben documentata, corrispondenza diretta tra istruzione simbolica e bit. Ogni istruzione che scriveremo avrà un effetto preciso e verificabile su registri, memoria e flag — nulla è nascosto da livelli di astrazione.

Perché queste distinzioni contano

Comprendere la differenza tra livelli di astrazione è fondamentale per tre ragioni pratiche nel contesto di questo corso:

// registri dedicati
L’Assembly richiede conoscenza dell’hardware — per questo l’8086 ha registri con funzioni specifiche (AX, CX, SP…)
// memoria esplicita
A basso livello non esiste la gestione automatica della memoria — ogni accesso richiede indirizzo, segmento e offset espliciti
// ISA specifica
Il codice Assembly è legato all’architettura — capire l’ISA dell’8086 significa capire il confine tra software e hardware

Riepilogo

  • Un algoritmo è la sequenza logica per risolvere un problema — indipendente dal linguaggio
  • Un programma è l’implementazione dell’algoritmo in un linguaggio eseguibile su un’architettura specifica
  • I linguaggi di alto livello (Python, C, Java) sono indipendenti dall’hardware e portabili
  • I linguaggi di basso livello (Assembly) richiedono conoscenza diretta di registri, dimensioni e indirizzamento
  • Il linguaggio macchina è l’unico formato eseguibile direttamente dalla CPU — sequenze binarie pure
  • L’Assembly è la rappresentazione simbolica del linguaggio macchina — corrispondenza quasi 1:1 con il binario
  • Il codice Assembly è non portabile — dipende dall’ISA del processore specifico
  • Studiare l’8086 in Assembly permette di vedere direttamente il rapporto tra istruzione, registro e bit

Lascia un commento