Valutazione attuale:  / 0
ScarsoOttimo 

Le macro istruzioni

Come ho già scritto in altro capitolo, la possibilità di scrivere macro-istruzioni mi aveva sempre affascinato e quando arrivò il 360 IBM questo sogno diventò realtà.

L'assembler del 360 offriva infatti finalmente la possibilità di scrivere dei macro-generatori che sarebbero serviti a generare intere routines; prima dell'avvento delle macro-istruzioni chi scriveva un programma in assembler doveva scrivere una linea di codice per ogni istruzione di macchina, mentre con l'uso delle macro-istruzioni era possibile che ad un'unica linea di codice source scritta dal pogrammatore corrispondessero decine o centinaia o anche migliaia di istruzioni di macchina; si capisce quindi quanto interessante fosse la prospettiva; io direi che lo stesso assembler, se arricchito da un gran numero di macro-istruzioni, sarebbe cominciato ad assomigliare ad un linguaggio avanzato; va notato anche che una routine generata da una macro ben collaudata, non avrebbe contenuto al suo interno alcun errore; quindi l'uso delle macro consentiva anche di ridurre notevolmente il numero di errori possibili.

Il Banco di Napoli installò il suo primo 360 (un modello 40) nel 1965; esso era destinato ad affiancare il 7070 sostituendosi inizialmente ai 1401, ma successivamente opportunamente potenziato, avrebbe dovuto sostituire anche l'ormai anziano 7070; questa migrazione durò circa 5 anni visto che i complessi programmi scritti per il 7070 dovevano essere completamente riscritti.

Naturalmente il 360 appena installato avrebbe dovuto ricevere e inviare dati al 7070, e per questo motivo si presentò subito il primo problema; i nastri scritti e leggibili dal 7070 erano a 7 piste e i dati erano codificati in BCD, quelli invece del 360 erano a 9 piste ed erano codificati in EBCDIC; per questo motivo la IBM aveva previsto che il 360 potesse anche collegare nastri a 7 piste e quindi noi fummo costretti ad averne alcuni per contentire il passaggio dei dati tra le due machine.

Ma purtroppo il problema non era soltanto hardware, infatti ricorderete che il 7070 dovendo rappresentare in memoria centrale i dati numerici e quelli alfanumerici in maniera diversa, usava inserire su nastro durante la scrittura dei dati un carattere (DELTA) che avvertiva quando si passava da dati numerici a dati alfanumerici; questo carattere naturalmente veniva ricevuto dal 360 quando leggeva nastri provenienti dal 7070 e doveva essere inserito sui nastri che il 360 preparava per il 7070.

Il problema era particolarmente grave quando (ed era la norma) i records logici erano scritti su nastro bloccati (cioè con numerosi records logici per ogni record fisico); se i records logici iniziavano in numerico, si verificava che un blocco ad esempio di 10 records lunghi 80 non risultava essere di 800 caratteri ma di 801, poichè all'inizio dell'intero blocco l'hardware del 7070 aveva inserito un carattere DELTA; un blocco siffatto non era leggibile dalla macro-istruzione di GET disponibile nel 360 perchè questa istruzione avrebbe prelevato dal buffer di lettura 100 caratteri alla volta a partire dal primo ed avrebbe fornito quindi al programma applicativo come primo record il DELTA seguito dai primi 99 caratteri del primo record logico e poi tutti i records successivi sfalsati di un carattere, infine si sarebbe rimasto un ulteriore record finale di lunghezza 1.

Per risolvere questo problema realizzai una prima macro-istruzione (la GET70) che considerava il record bloccato come un unico record UNDEFINED cioè un record contenente un unico record logico; al primo suo uso la macro provvedeva a leggere un blocco di dati in modo UNDEFINED, se all'inizio del blocco letto trovava un DELTA si posizionava sul carattere immediatamente successivo e forniva al programmatore come inizio del primo record logico quell'indirizzo di buffer, alla successiva GET70 incrementava il vecchio indirizzo della lunghezza del record logico (comunicato alla GET70 dal programmatore) e forniva così il record successivo; quando tutto il buffer era stato utilizzato, la macro provvedere a leggere il blocco successivo e a ripetere su di esso lo stesso trattamento; naturalmente con un procedimento inverso creai anche la macro PUT70 che provvedeva a scrivere i dati su nastri in maniera inserendo quando necessario il carattere DELTA che era necessario affinchè il nastro fosse leggibile dal 7070.

Queste le primissime macro create, esse erano state precedute soltanto da alcune altre scritte al solo scopo di sperimentarne l'uso ( la EDITS che generava le poche istruzioni necessarie per esporre un campo numerico con soppressione degli zeri non significativi e la EDITP che invece consentiva di esporre un campo numerico con soppressione degli zeri non significativi e con la punteggiatura per la divisione in migliaia); immediatamente dopo avevo scritta l'ARRANGE che richimava la EDITS e la EDIP e consentiva di esporre un insieme di dati editati.

Dopo aver apprezzato i grossi risultati ottenuti con l'uso della GET70 e PUT70 la direzione si rese conto dell'enorme quantità di lavoro che avevo fatto risparmiare ai programmatori applicativi e mi lasciò libero di pensare a sempre nuove soluzioni di quel genere.

Poichè ogni programma doveva iniziare con una routine che inizializzasse i registri base, scrissi immediatamente la macro BEGIN che ricevendo come parametri l'elenco dei registri da caricare, provvedeva a generare tutte le istruzione necessarie all'inizializzazione dei registri stessi; all'inizio di ogni programma quindi i programmatori applicativi dovevano soltanto scrivere una macro BEGIN con l'elenco dei registri da usarsi.

Voglio qui ricordare che la programmazione del 360 richiedeva che in ogni programma il registro 13 fosse sempre tenuto impostato a puntare un'area di memoria interna al programma stesso di 15 word nella quale quando necessario le routines eventualmente richiamate dalle macro IBM avrebbero salvato tutti i registri prima di utilizzarli per le proprie necessità e dalla quale avrebbero ripristinato i registri stessi al termine dell'esecuzione prima di rientrare nel programma chiamante; dunque la regola usata da tutti i programmatori, e anche insegnata dagli istruttori dell'IBM era di non utilizzare il registro 13 come registro base in quanto il suo uso era riservato alla funzione indicata prima.

Data la nota penuria di registri, il fatto che si dovesse ...sciupare il registro 13 per puntare un'area di solo 15 voci (60 bytes soltanto) mi innervosiva, ed allora pensai di definire quell'area di 60 bytes all'inizio del programma e di farvi puntare, come voleva l'IBM il registro 13; poichè pero' dopo quell'area iniziava il programma vero e proprio, mi potevo permettere anche di utilizzare il registro 13 come primo registro base guadagnando quindi un registro; questa soluzione fu inserita nella macro BEGIN e quindi da allora i programmatori non solo si avvalevano automaticamente di un registro base in più che non era necessario neanche dichiarare tra i parametri, ma si trovavano anche generate automaticamente le istruzioni per effettuare l'impostazione del registro 13.

Il mio lavoro di creazione di sempre nuove macro proseguì per anni, ma quelle che possono considerarsi una vera serie a se stante sono certamente le macro di I/O che infatti per essere descritte richiedono un apposito capitolo. 

 

Torna all'indice