di  -  lunedì 20 giugno 2011

Nel precedente articolo abbiamo introdotto il Debug Monitor e abbiamo accennato alle funzioni base che dovrebbe avere un sistema operativo minimale, per consentire l’esecuzione di semplici programmi sulla macchina.

Ad essere precisi, su questo genere di macchine non è indispensabile un vero Sistema Operativo, ma torna molto utile avere a disposizione delle funzioni generiche che siano quanto più possibile indipendenti dalla piattaforma. L’indipendenza dalla piattaforma consente, teoricamente, di riutilizzare lo stesso codice su macchine diverse purché queste dispongano di un livello di astrazione compatibile.

In questa ottica di astrazione, parola chiave di questo articolo, i computer ad 8 bit della casa americana Commodore venivano dotati del cosiddetto KERNAL: Keyboard Entry Read, Network And Link.

Si, lo so, l’acronimo non vuol dire assolutamente nulla. Infatti è quasi certo che il nome KERNAL sia nato da una storpiatura della parola Kernel, e solo in un secondo momento sia stato inventato l’acronimo per giustificare la nuova parola (classico esempio di acronimo inverso).

Nella documentazione del Commodore PET2001, del 1977, si parla correttamente di Kernel. Successivamente, a quanto pare, il progettista Robert Russell scrisse erroneamente la parola KERNAL (con la A) nei suoi appunti per il Commodore VIC20 e, nello scrivere la documentazione tecnica per lo stesso, nel 1980, pare che i due addetti Neil Harris e Andy Finkel abbiano trascritto la parola con il suo nuovo/errato spelling.

L’astrazione offerta dal KERNAL consiste in una semplice ma utile raccolta di funzioni essenziali, che spaziano dalla gestione della comunicazione seriale alla manipolazione dei files, passando per le routine di gestione dello schermo e della tastiera.

Queste funzioni hanno degli indirizzi fissi in memoria (nell’ultima pagina dell’address space) ed espongono al programmatore un’interfaccia ben definita per richiedere i servizi previsti dal sistema.

Arriviamo subito ad un esempio concreto per chiarire meglio le idee: Apertura di un file e caricamento in memoria dello stesso.

In linguaggio BASIC questo sarebbe equivalente al semplicissimo comando LOAD “NOMEFILE”,D,S dove D ed S sono due numeri interi che identificano la periferica di lettura (8,1 per specificare ad esempio il primo floppy drive del bus seriale). L’interprete BASIC non contiene direttamente il codice per gestire tutto il lavoro, ma si limita a riutilizzare alcune funzioni del KERNAL che sono:

  • SetLFS per selezionare la periferica con i numeri D ed S (D = Device Number, S = Secondary Address)
  • SetNAM per selezionare il nome del file passando la stringa “NOMEFILE” come parametro
  • Load per caricare il file precedentemente selezionato in una determinata zona di memoria (variabile in base alla versione dell’interprete BASIC, alla mappa di memoria e al modello di computer Commodore usato).

Nello specifico, queste funzioni (SetLFS, SetNAM, Load) vengono identificate da specifici indirizzi di memoria (rispettivamente FFBA, FFBD e FFD5) che, a loro volta, contengono un’istruzione di salto ad un secondo indirizzo contenente il vero codice della funzione. Questo consente di avere degli indirizzi prefissati indipendentemente dalla versione del KERNAL, da cui deriva l’efficacia dell’astrazione.

Se vogliamo chiamare la funzione Load, quindi, dobbiamo semplicemente eseguire un’istruzione di Call all’indirizzo FFD5, la CPU troverà a quell’indirizzo un’ulteriore istruzione di salto (variabile in base alla versione del KERNAL) che porterà all’esecuzione della funzione vera e propria. Alla fine della funzione di Load, il KERNAL conterrà un’istruzione di Return che consentirà al programma utente di proseguire con il suo codice.

Le istruzioni Call e Return, nel linguaggio macchina dei processori 6502 e derivati, sono implementate rispettivamente dagli opcode JSR e RTS.

Jump to SubRoutine salva il Program Counter sullo stack (in realtà salva l’indirizzo della prossima istruzione meno 1) ed esegue un salto all’indirizzo specificato. ReTurn from Subroutine fa l’operazione inversa, cioè preleva il contenuto dello stack e lo riposiziona sul Program Counter (dopo aver sommato 1), eseguendo di fatto un salto all’indietro.

Come vengono passati i parametri per le funzioni? Nel nostro caso specifico, dobbiamo passare minimo 3 parametri, cioè il Device Number, il Secondary Address e la stringa contenente il File Name.

Ciascuna funzione del KERNAL ha un suo modo per ricevere i parametri e questi sono ben documentati. Tipicamente, per le funzioni con un solo parametro, basta scrivere il valore nell’accumulatore (registro A). Le funzioni che gestiscono regioni di memoria, come array o stringhe, invece prendono come parametro la lunghezza del buffer in A e l’indirizzo del buffer nella coppia di registri X e Y.

Questo documento contiene l’elenco delle funzioni del KERNAL, completo di indirizzo della funzione (da usare nell’istruzione di Call, cioè JSR), della modalità di passaggio dei parametri e di eventuali valori di ritorno. Nell’elenco sono presenti inoltre l’elenco dei registri che vengono “toccati” dalle funzioni e l’indirizzo “reale” delle funzioni. Tuttavia bisogna prendere queste informazioni con le pinze, perchè sono specifiche del Commodore 64.

Se vogliamo rispettare la filosofia di astrazione del KERNAL, dobbiamo ignorare queste informazioni e attenerci agli indirizzi fissi del cosiddetto KERNAL Vector. In particolar modo, dobbiamo sempre supporre che tutti i registri vengano modificati, e quindi salvarli sullo stack all’occorrenza, sempre per lo stesso motivo.

A titolo esemplificativo prendiamo la funzione CHRIN, che legge un byte dalla periferica di input standard (normalmente la tastiera). Secondo la tabella di prima, l’indirizzo reale della funzione sarebbe F157, ed i registri modificati sono A, che conterrà il byte letto, ed X che viene usato come variabile temporanea.

Per ottimizzare il codice potremmo essere tentati di salvare soltanto il contenuto del registro X e di fare direttamente una JSR verso l’indirizzo reale F157, piuttosto che l’indirizzo fisso FFCF.

Sebbene questo sia perfettamente lecito sulla macchina di riferimento (il Commodore 64 in questo caso), quasi sicuramente non funzionerà su tutte le altre macchine per almeno 2 motivi:

  1. Non è detto che tutte le implementazioni abbiano il proprio indirizzo reale esattamente in F157. Mentre è garantito dal KERNAL che l’indirizzo fisso FFCF sia sempre rispettato in tutte le sue versioni.
  2. Non è detto che tutte le implementazioni sporchino soltanto il registro X. Diversi modelli di computer, con differenti chip di I/O e di conseguenza diverse routine di interfacciamento, potrebbero sporcare anche il registro Y, quindi è buona norma salvare tutti i registri che ci interessano.

Tramite questo semplice esempio, abbiamo visto come sia possibile costruire un livello di astrazione molto elementare. Il KERNAL consente, se usato correttamente, di effettuare il porting di un programma in codice macchina su più modelli di computer Commodore in modo relativamente semplice.

Grazie alla sua struttura possiamo sicuramente considerarlo come un esemplare rudimentale di Sistema Operativo, perché fornisce, a modo suo, alcuni dei servizi più importanti: l’astrazione dell’hardware tramite la gestione dei files e delle periferiche.

Per concludere questa panoramica, un link utile contenente la descrizione completa delle istruzioni delle CPU della famiglia 6502 http://www.6502.org/tutorials/6502opcodes.html

Nel prossimo articolo punteremo un po’ più in alto e mostreremo un altro concetto fondamentale dei Sistemi Operativi, che si aggiunge all’astrazione dell’hardware, ed è il cosiddetto task. Tramite il task si introduce un secondo livello di astrazione, cioè l’astrazione del software. Suona strano? Lo vedremo nel prossimo articolo!

28 Commenti »

I commenti inseriti dai lettori di AppuntiDigitali non sono oggetto di moderazione preventiva, ma solo di eventuale filtro antispam. Qualora si ravvisi un contenuto non consono (offensivo o diffamatorio) si prega di contattare l'amministrazione di Appunti Digitali all'indirizzo info@appuntidigitali.it, specificando quale sia il commento in oggetto.

  • # 1
    demo
     scrive: 

    sys64738

  • # 2
    iva
     scrive: 

    Azz, mi ero perso il primo articolo… bella serie, continua cosi’!

    Un piccolo appunto: gli articoli potresti farli anche piu’ lunghi (alla Cesare, per intenderci!), mi interessano molto i dettagli e divagazioni varie, forse non sono il solo :)

  • # 3
    Eroes
     scrive: 

    Estremamente interessante davvero.
    Congratulazioni ;)

  • # 4
    Fog76
     scrive: 

    Questa era informatica!!!!

    E vai di nostalgia :-)

  • # 5
    banryu
     scrive: 

    Da programmatore hobbista ignorante del “basso livello” trovo questa serie molto interessante, e in generale i tuoi articoli si fanno leggere molto volentieri.
    Grazie :-)

  • # 6
    Davide
     scrive: 

    Load”$”,8,1 per far partire i giochini sul commodore 64 da bambino…mi sembra 1000 anni fa…

  • # 7
    Antonio Barba (TheKaneB) (Autore del post)
     scrive: 

    @demo: che hai combinato? improvvisamente mi si è rimpicciolito lo schermo e si è blocc….

    @iva: beh, Cesare è più bravo di me in queste cose… io mi dedico più alla divulgazione semplificata che è quello che mi riesce meglio :-) Comunque farò in seguito qualche approfondimento su temi specifici, per accontentare tutti i palati :-)

    @Fog76: Questa è SPARTAAAAA degli informatici :-D

    @banryu: Grazie mille! Il mio intento è proprio quello di avvicinare i lettori curiosi alle questioni di basso livello, che oggi sono sempre più ignorate dai più grazie a / per colpa di sistemi via via più sofisticati e di alto livello. Penso che sia importante conoscere le architetture (hardware e software) dei computer più semplici ed elementari, per comprendere meglio la complessità dell’informatica moderna.

  • # 8
    Lorenzo
     scrive: 

    poke 780,65
    sys 65490

    Stampare una “A” in questo modo non ha prezzo!!!

  • # 9
    Marco
     scrive: 

    “Load”$”,8,1″

    Questo casomai ti fa la ‘dir’ del disco ;-)

  • # 10
    darksax
     scrive: 

    “Load”*”,8,1″

    o ricordo male???

  • # 11
    Massimo M
     scrive: 

    Mi chiedevo se fosse possibile da parte di qualche anima pia fare un riferiemto allo Spectrum. Non per fanboy o altro (è passato troppo tempo, almeno per me!) ma un piccolo parallelismo sarebbe molto comodo per valutare le differenza. Anche se cono sicuro quasi al 100% che le cose siano (quasi) identiche. Altrimenti … che altro modo c’è ?

  • # 12
    iva
     scrive: 

    LOAD”$”,8
    LIST

    per la dir del disco

    LOAD”*”,8,1

    per giocare!

    …e aggiungo anche:
    SHIFT + RUN/STOP

    per fare load and run da cassetta :)

  • # 13
    dani
     scrive: 

    @Fog76

    Senza essere polemico per me quella non era vera informatica, ma più che altre elettronica ramificata nell’informatica, di un’era epica, in cui per tirare qualche frame in più bisognava andare ben dentro al sistema e sfondare le bariere dei linguaggi. Io penso più alla vera informatica come qualcosa come la macchina di turing o le funzioni parzialmente ricorsive in cui ci si concentra più sugli algoritmi da implementare che sul modo.

    my 2 cents.

  • # 14
    Antonio Barba (TheKaneB) (Autore del post)
     scrive: 

    @Massimo: Sono a digiuno di Spectrum, quando avrò il mio Spectrum e lo studierò per bene stai sicuro che tornerò alla carica sull’argomento :-)

    @dani: in realtà avete ragione entrambi, il problema sta nella lingua italiana che è un po’ carente di termini tecnici. Per Informatica, in italiano, si intende l’unione di “Computer Science”, “Computer engineering” e “Software Engineering”. La prima riguarda la teoria della computazione, quindi Turing Machines, FSM, Linguaggi Formali, lambda calculus, ecc… La seconda si riferisce invece all’elettronica digitale orientata al calcolo, mentre la terza si riferisce allo studio di design patterns, language design e project managing…

  • # 15
    dani
     scrive: 

    @Antonio Barba

    Una cosa che mi piace di questo portale è che gli autori non si fermano a scrivere gli articoli, ma leggono anche i commenti per discuterne insieme.
    Per risponderti, hai ragione! E, secondo me esistono in italiano qualcosa del tipo ingegneria informatica, scienza dell’informazione, architettura del software o qualcosa del genere ma non ho tempo di cercare per essere più preciso. Purtroppo a volte siamo noi che tagliamo questa nostra lingua e per fare in fretta accorciamo raggruppando tutto in un sola parola per fare prima.
    Cmq bel articolo, mi fa venire in mente le mie traversie con lo Z80 e tutti i giri che bisognava fare per tirare fuori qualcosa di decente altra epoca, che da un parte rimpiango ma dall’altra no (vista la fatica!)

  • # 16
    Antonio Barba (TheKaneB) (Autore del post)
     scrive: 

    @dani: senz’altro esistono termini più specifici, ma quando diciamo “informatica” stiamo parlando di una cosa troppo generica…

    Stesso discorso quando diciamo “meccanica”. Ci riferiamo alla fisica newtoniana? all’ingegneria delle macchine? al mestiere di riparare i motori a scoppio? boh… :-D

    e che ne dici di “Ottica”? potrebbe essere una branca della fisica, un sinonimo di “punto di vista”, o un negozio di binocoli e occhiali da sole :-D

    Per quanto riguarda articoli e commenti, sono convinto che i commenti costituiscano parte integrante dell’argomento, perchè quasi sempre vanno ad integrare l’articolo stesso con precisazioni, correzioni, aggiunte, spunti di approfondimento e così via :-)
    Se non fosse per la qualità dei commenti non sarei spronato a scrivere :-)

  • # 17
    Davide
     scrive: 

    Vero,load”$”,8,1 era per caricare la dir del disco….il tempo a volte offusca la memoria!
    load “*”,8,1 era per giocare…

  • # 18
    Z80Fan
     scrive: 

    Bene bene si comincia a salire di livello (d’astrazione si intende) :).

    Forse è importante dire che la struttura con i jump viene chiamata appunto Jump (o branch) Table; secondo me è un utile termine da conoscere ;)

    @Massimo M:
    Ho sentito nominare lo Spectrum? :D

  • # 19
    sisko212
     scrive: 

    Ora che c’è l’hai guarda che ci faiiiiiii !!!!!
    http://www.youtube.com/watch?v=lcbmPd9k018&feature=related

  • # 20
    Massimo M
     scrive: 

    Ingegneria del software. Ci ho fatto la tesi :-)

  • # 21
    Fog76
     scrive: 

    Con il mio commento non volevo scatenare una piccola guerra :-)

    Solo che i retrosistemi e processori 8 bit sono la mia passione, e quando si ama una cosa si vedono solo pregi. Certo che è più comodo oggi sviluppare un software quando si hanno 2 giga di ram, ide o rad potentissimi, database relazionali, librerie già pronte, gui che rendono l’utilizzo del software molto più comodo e una miriade di linguaggi tra cui scegliere quello più consono alla nostra causa…

    Solo che ogni volta che accendo il mio C64 o il mio Spectrum (ma anche l’MSX, etc etc), provo una tenerezza e un calore che i moderni sistemi non mi danno; ma questo è solo dovuto alla mia età e al fatto che da bambino sbavavo sul C64 (e mio padre mi comprò l’Olivetti PC 128, ma grazie a questa macchina imparai a programmare, visto che di giochi ne esistevano veramente pochi…

  • # 22
    Mazzulatore
     scrive: 

    @Davide
    “Vero,load”$”,8,1 era per caricare la dir del disco….il tempo a volte offusca la memoria!”
    Infatti il comando non funziona, se non erro restituisce file not found.
    Come ha detto iva per la directory del disco il comando è:
    load”$”,8 (senza ,1)

    :p

  • # 23
    MauSeventyOne
     scrive: 

    Ah quanti ricordi… :D rileggere gli opcode JSR, RTS mi fa scendere una lacrimuccia :’)

  • # 24
    Felice Pescatore
     scrive: 

    Hmmm… ricordo all’università il corso di Calcolatori e il simulatore MMIX… e ho ancora gli incubi a pensare all’algoritmo merge sort in assembler.

  • # 25
    zephyr83
     scrive: 

    Load”*”,8,1 se nn ricordo male lo usavo per le cassette mentre per i floppy disk caricava direttamente il primo gioca della lista
    Load”$”,8 invece doveva esser accompagnato dal comando list, poi andare alla riga del gioco e scrivere di nuova load all’inizio (e mi pare pure ,8 alla fine) e infine dare run :)

  • # 26
    Antonio Barba (Autore del post)
     scrive: 

    guarda un po’ quanti commodoriani si sono adunati :-D

    chiudo l’OT tentando di spegnere ogni vostro dubbio sul comando LOAD:

    Se avete il secondo floppy, potete usare LOAD “NOME”,9 invece di ,8 perchè quel numeretto è il Device Number.
    Il terzo parametro “NOME”,8,1 è il Secondary Address. Se 0 carica il programma nella memoria BASIC, se 1 lo carica all’offset specificato dai primi 2 byte del file (programmi in Linguaggio Macchina).

    LOAD “*” oppure LOAD “*”,1
    carica il primo programma che trova sul nastro. Il nastro è il Device #1. Se non viene specificato viene sempre considerato il nastro.

    LOAD “*”,8,0 oppure LOAD “*”,8 (lo 0 è implicito)
    carica il primo programma BASIC dal floppy (il floppy ha un device number compreso tra 8 e 15, di solito 8)

    LOAD “*”,8,1
    carica il primo programma in linguaggio macchina dal floppy.

    LOAD “$” oppure ,1 (cassetta, default) oppure ,8 (floppy)
    carica l’indice di tutti i programmi (se lo fate su nastro, buona notte)

    in entrambi i casi ci vuole un LIST per vedere la directory

    LOAD “NOME” oppure ,1 (cassetta, default) oppure ,8 (floppy)
    carica il programma BASIC chiamato “NOME”

    LOAD “NOME”,1,1 oppure ,8,1
    carica il programma in LM chiamato “NOME”

    Dopo il caricamento di un programma ci stava quasi sempre un bel RUN, ma alcuni partivano in automatico :-)
    I programmi in linguaggio macchina solitamente avevano come unico comando BASIC una istruzione SYS 12345 dove 12345 è l’indirizzo di partenza del programma e il comando SYS serve a lanciare una routine, una specie di Jump in linguaggio BASIC.

  • # 27
    sisko
     scrive: 

    A parte la questione nostalgica, e che ancora oggi, di tanto in tanto accendo il mio C64 e Amiga, e che mi pento e mi dolgo di non essere mai riuscito a fare qualcosa di serio con l’assembler del C64-6502; mi chiedo però dove si voglia arrivare con questa serie di articoli… è solo per un revival nostalgico-informatico, o è per gettare le basi per un discorso piu ampio ?

  • # 28
    Antonio Barba (Autore del post)
     scrive: 

    @sisko: ovviamente la seconda che hai detto… non hai notato la prima parte del titolo? (Hint: “Dentro i Sistemi Operativi – […]” ?

    ;-)

Scrivi un commento!

Aggiungi il commento, oppure trackback dal tuo sito.

I commenti inseriti dai lettori di AppuntiDigitali non sono oggetto di moderazione preventiva, ma solo di eventuale filtro antispam. Qualora si ravvisi un contenuto non consono (offensivo o diffamatorio) si prega di contattare l'amministrazione di Appunti Digitali all'indirizzo info@appuntidigitali.it, specificando quale sia il commento in oggetto.