Il reverse engineering è una pratica di per sé legale che consiste nell’analizzare un prodotto esistente per comprenderne il funzionamento interno. Di solito questa pratica viene utilizzata per individuare problemi di compatibilità e di sicurezza ma spesso può essere sfruttata per creare prodotti simili. Per questo, soprattutto nel caso dei software, i termini di licenza d’uso vietano espressamente il reverse engineering.
L’Intel 8086 è il primo processore x86 a 16 bit che fu introdotto nel 1978 (della corsa e del significato di 8, 16, 32, 64 bit parliamo in un altro articolo).
Anche se è stato rapidamente sostituito da processori molto più potenti e versatili, l’Intel 8086 ha avuto un impatto significativo sulla storia dell’informatica.
Basato sull’architettura di Von Neumann, con un’unità di elaborazione centrale (CPU) che comunica con la memoria attraverso un bus a 16 bit, Intel 8086 operava con una frequenza di clock compresa tra i 4,77 e 10 MHz a seconda del modello.
Intel 8086 disponeva di 14 registri a 16 bit e poteva indirizzare fino a 1 Megabyte di memoria anche se, a causa delle limitazioni del bus a 16 bit, venivano di fatto usati appena 640 KB nella maggior parte dei sistemi in segmenti da 64 KB.
In termini di prestazioni l’8086 raggiunse il valore di circa 0,33 MIPS (milioni di istruzioni al secondo) a 5 MHz anche se il risultato era inferiore rispetto all’offerta a 16 bit di altre aziende, ad esempio il Motorola 68000.
Saperne di più, grazie al reverse engineering, sul funzionamento interno di un processore così importante può essere utile per comprendere meglio quelle “idee vincenti” che hanno contribuito all’esplosione del fenomeno personal computing all’inizio degli anni ’80. Proprio in questi giorni, tra l’altro, vengono festeggiati i 40 anni dalla nascita dell’IBM PC-XT.
Ken Shirriff, uno dei più noti esperti a livello mondiale di reverse engineering, ha pubblicato una serie di interessantissimi post che offrono uno spaccato estremamente preciso e, dal nostro punto di vista, anche molto suggestivo, sui “segreti” di un processore storico come l’Intel 8086. Il lavoro svolto da Shirriff ha un’inestimabile valenza sul piano della conoscenza, della conservazione del patrimonio tecnologico e dello sviluppo di tecnologie future.
Spiegando come funziona un processore abbiamo chiarito per sommi capi i principi di base che accomuna lo sviluppo di qualunque unità di elaborazione (CPU).
L’esperto ha “retroingegnerizzato” l’8086 partendo proprio dal die in silicio pubblicando poi una serie di foto della circuiteria acquisite al microscopio.
In un primo articolo Shirriff si è concentrato sulla gestione degli interrupt nel processore 8086: gli interrupt sono segnali hardware o software che indicano al processore di interrompere l’esecuzione del programma corrente e passare ad eseguire un’altra parte di codice. Una corretta gestione degli interrupt è importante perché permette di garantire la corretta esecuzione dei programmi, di assicurare che le operazioni vengano eseguite senza errori e la tempestività nell’elaborazione (alcuni segnali necessitano di una gestione senza ritardi e di una risposta immediata da parte del processore).
Come la maggior parte dei processori, anche l’8086 fornisce registri più veloci della memoria principale: i registri hanno lo scopo di consentire il flusso dei dati da un luogo all’altro del sistema e memorizzare valori.
Shirriff spiega che l’8086 poggia su uno schema complicato per selezionare quale registro utilizzare, con una combinazione di microcodice e hardware.
Intel 8086 rappresenta i registri con un numero a 5 bit; una scelta insolita rispetto ai precedenti microprocessori che selezionavano i registri direttamente a partire dall’istruzione o dai circuiti di controllo.
In un altro approfondimento il ricercatore si concentra sul ModR/M addressing microcode, componente divenuto importante nella pipeline di esecuzione x86, ovvero sul microcodice usato per decodificare le istruzioni macchina e indirizzare gli operandi in memoria.
Il processore 8086 integra inoltre un complesso set di istruzioni in cui le singole istruzioni possono avere una lunghezza compresa da uno a sei byte. Come fa il processore a stabilire la lunghezza di un’istruzione? Shirriff dettaglia bene il funzionamento dell’interessante algoritmo usato nell’8086 per determinare quanti byte utilizzare per un’istruzione.
Infine, si parla di moltiplicazione: mentre oggi i programmatori danno per scontata la moltiplicazione svolta a livello di processore, la maggior parte dei microprocessori negli anni ’70 poteva solo sommare e sottrarre. La moltiplicazione richiedeva un ciclo lento e noioso implementato a livello di codice assembly.
L’8086 forniva istruzioni macchina per la moltiplicazione ed era in grado di moltiplicare numeri a 8 o 16 bit con una singola istruzione implementata nel microcodice. Anche così, la moltiplicazione era un’operazione lenta, da 24 a 30 volte più lenta dell’addizione.