Sei sulla pagina 1di 5

SPOSTAMENTO DEI CAMPI DECIMAL

Lo spostamento in quanto tale non è fornito nelle operazioni decimali System/360. Come in altri
computer a lunghezza di campo variabile, l'equivalente dello spostamento viene eseguito mediante
combinazioni appropriate di istruzioni di movimento dei dati. La questione è resa un po' più complessa
dal fattore dei formati compressi, con due cifre per byte e dallo stato speciale della posizione del segno.
Questo è un piccolo prezzo da pagare per la maggiore economia di memoria della disposizione a due
cifre per byte.

È inoltre necessario prestare attenzione quando si devono manipolare campi sovrapposti, per essere
sicuri che nessun dato venga distrutto. Questa è un'altra occasione in cui è assolutamente essenziale
ricordare che tutti gli operandi sono indirizzati dal byte più a sinistra.

Spostamento a destra
Cominciamo con il tipo di spostamento più semplice: uno spostamento decimale a destra di un numero
pari di cifre. Supponiamo di avere un numero di cinque byte e nove cifre in SOURCE; dobbiamo spostarlo
in un campo di cinque byte denominato DEST con le ultime due cifre eliminate e due zeri a sinistra.
Possiamo farlo in due modi: con o senza “sporcare” il contenuto originale di SOURCE. Facciamolo prima
senza “sporcamento”. Supponiamo che i due campi contengano originariamente:

SOURCE DEST
12 34 56 78 9S 55 55 55 55 55

La S sta per un segno più o meno, qualunque esso sia. Le istruzioni per effettuare lo spostamento
potrebbero essere le seguenti, dove abbiamo mostrato anche il contenuto dei due campi dopo
l'esecuzione di ciascuna istruzione:

SOURCE DEST
MVC DEST+1(4),SOURCE 12 34 56 78 9S 55 12 34 56 78
MVN DEST+4(1),SOURCE+4 12 34 56 78 9S 55 12 34 56 7S
MVC DEST(l),ZERO 12 34 56 78 9S 00 12 34 56 7S

Nella prima istruzione Move Characters viene specificata una lunghezza esplicita pari a 4; questa
lunghezza si applica a entrambi i campi. Dato che l'indirizzo del primo operando è DEST+ 1, i quattro
byte della destinazione sono i quattro più a destra. Il secondo operando è dato semplicemente come
SOURCE, quindi i quattro byte sono quelli più a sinistra. Le ultime due cifre (un byte) sono state
eliminate.

Ma nel frattempo anche il segno è caduto. Di conseguenza utilizziamo un'istruzione Move Numeric per
collegarlo al numero spostato. Questo deve essere fatto con una lunghezza esplicita pari a uno, per
evitare di disturbare qualsiasi cifra di DEST. Entrambi gli indirizzi devono essere scritti con il "+4" per
individuare il singolo carattere corretto. Infine, spostiamo un byte di una costante denominata ZERO
(non mostrata), che contiene zeri, nel primo byte di DEST. Questo azzera tutto ciò che potrebbe esserci
stato prima.
Se il contenuto di SOURCE non deve essere preservato nella sua forma originale, la sequenza seguente è
leggermente più breve.

SOURCE DEST
MVN SOURCE+3(1),SOURCE+4 12 34 56 7S 9S 55 55 55 55 55
ZAP DEST,SOURCE(4) 12 34 56 7S 9S 00 12 34 56 7S

Il Move Numeric sposta il segno sul byte che conterrà il segno nel risultato finale. Zero e Add prelevano
quattro byte di SOURCE e li aggiungono a DEST dopo aver azzerato DEST. Zero e Add hanno due codici di
lunghezza. Per DEST usiamo la lunghezza implicita di 5; per SOURCE è necessario fornire una lunghezza
esplicita per eliminare le ultime due cifre.

Supponiamo infine che per qualche motivo sia necessario lasciare il risultato spostato in SOURCE, senza
ricorrere all'espediente di spostare semplicemente il segno e accodare degli zeri a sinistra.

SOURCE
MVN SOURCE+3(1),SOURCE+4 12 34 56 7S 9S
ZAP SOURCE,SOURCE(4) 00 12 34 56 7S

Il movimento del segno è come prima. Nello Zero e nell'Add, il secondo operando è dato come
SOURCE( 4), che significa un campo di quattro byte il cui byte più a sinistra ha l'indirizzo SOURCE; questo
è solo 12 34 56 7S. Il primo operando è semplicemente SOURCE, con la sua lunghezza implicita pari a 5,
che significa l'intero campo.

È importante sapere che questo tipo di sovrapposizione è consentito quando il campo del primo
operando è lungo almeno quanto il secondo operando, ma non quando è troppo corto per contenere
tutte le cifre significative del secondo operando. Un piccolo studio mostra che una violazione di questa
regola comporterebbe la distruzione dei byte del secondo operando prima che vengano spostati.

Passiamo ora a uno spostamento leggermente più complesso, che coinvolge un numero dispari di posti.
Ciò richiede l'utilizzo di un'istruzione speciale progettata allo scopo, il Move con Offset. L'azione di
questa istruzione può essere descritta come segue. Il segno del primo operando non viene disturbato; il
secondo operando è posizionato a sinistra e adiacente ai quattro bit di ordine inferiore (i bit di segno)
del primo operando. Qualsiasi posizione di cifra di ordine superiore non utilizzata nel primo operando
viene riempita con zeri.

Guardando un esempio, prendiamo i campi descritti nell'illustrazione precedente, ma supponiamo che


lo spostamento debba essere di tre posizioni invece di due.

SOURCE DEST
MVO DEST,SOURCE(3) 12 34 56 78 9S 00 01 23 45 65
MVN DEST+4(1),SOURCE+4 12 34 56 78 9S 00 01 23 45 6S
Nel Move with Offset, il secondo operando è dato come SOURCE(3), che preleva un campo di tre byte
che inizia da sinistra, vale a dire i byte contenenti 12 34 56. Il primo operando è DEST, con la sua
lunghezza implicita di 5. Le cifre 12 34 56 vengono spostate in DEST con un offset di quattro bit, o una
cifra, lasciando 00 01 23 45 65 in DEST; il 5 più a destra è quello che c'era all'inizio. Un movimento
numerico finale associa il segno di origine al campo di destinazione.

Se è necessario nello spostamento lasciare il risultato in SOURCE, è necessaria una sola istruzione,
poiché l'istruzione Move with Offset non ha effetto sul segno del primo operando e l'estremità sinistra
del campo ricevente è riempita di zeri.

SOURCE
MVO SOURCE,SOURCE(3) 00 01 23 45 6S
I campi sovrapposti qui non causano problemi, poiché ancora una volta il movimento è a destra del
contenuto originale. (In realtà, è consentita qualsiasi sovrapposizione; è responsabilità del
programmatore assicurarsi che il risultato sia significativo.)

Spostamento a sinistra
Uno spostamento a sinistra presenta problemi leggermente diversi. Questa volta supponiamo di avere
un campo sorgente di tre byte e uno di destinazione di cinque.

Prima SOURCE DEST


12 34 5S 99 99 99 99 99

Prendiamo il nostro problema, per spostare il numero da SOURCE a DEST, con quattro zeri a destra in
DEST e con DEST pronto per fare aritmetica. Di seguito è mostrata una sequenza accettabile di istruzioni.

SOURCE DEST
MVC DEST(3),SOURCE 12 34 5S 12 34 5S 99 99
MVC DEST+3(2),ZEROS 12 34 5S 12 34 5S 00 00
MVN DEST+4(1),DEST+2 12 34 5S 12 34 5S 00 0S
MVN DEST+2(1),ZEROS 12 34 5S 12 34 50 00 0S

Il primo Move Characters necessita di una lunghezza esplicita su DEST; in caso contrario, la lunghezza
verrebbe, impropriamente per il nostro problema, interpretata da DEST come 5. Gli ultimi due byte di
DEST non vengono influenzati dal primo movimento; un secondo li cancella. Un movimento numerico
trasferisce il segno e un secondo movimento numerico cancella il segno ora estraneo che accompagnava
i dati di origine sul primo Move Characters.

È disponibile un altro modo per eliminare il segno estraneo utilizzando l'istruzione And Immediate.
"Anding" due quantità dà un risultato che ha un bit 1 ovunque entrambi gli operandi avevano 1 e uno
zero altrove. Ad esempio, se facciamo "AND" di 1100 e 1010, il risultato è 1000; solo nella posizione del
primo bit entrambi gli operandi ne avevano uno.
Nell'istruzione And Immediate (NI), entrambi gli operandi sono lunghi esattamente otto bit. Uno di essi è
dato dal byte specificato dall'indirizzo; l'altro è contenuto nell'istruzione stessa (da qui il termine
"immediato"). Il risultato sostituisce il byte specificato in memoria. Nell'esempio in questione,
desideriamo lasciare i primi quattro bit del byte su DEST+2 così come erano; questo può essere fatto
posizionando gli uno nelle posizioni corrispondenti nella parte dell'istruzione che sarà oggetto
dell’"And". (Questa è solitamente chiamata maschera.) Desideriamo azzerare i quattro bit corretti di
DEST+2, qualunque fossero prima; questo può essere fatto inserendo degli zeri in quella parte della
maschera. La maschera, in sintesi, dovrebbe essere 1111 0000, espressa in binario.

Per scrivere l'istruzione, possiamo convertirla nel suo equivalente decimale 240, o, meglio, scriverla in
esadecimale, X'F0'. In altre parole, possiamo sostituire l'ultima istruzione con una delle seguenti:

NI DEST+2,240
NI DEST+2,X'F0'
Infine, considera uno spostamento a sinistra di un numero dispari di posti. Ad esempio, prendiamo i dati
dell'illustrazione precedente, ma supponiamo che ci siano tre zeri a destra invece di quattro.

SOURCE DEST
Prima 12 34 5S 99 99 99 99 99
MVC DEST(3),SOURCE 12 34 5S 12 34 5S 99 99
MVC DEST+3(2),ZEROS 12 34 5S 12 34 5S 00 00
MVN DEST+4(1),DEST+ 2 12 34 5S 12 34 5S 00 0S
NI DEST+2,X'F0' 12 34 5S 12 34 50 00 0S
MVO DEST(4),DEST(3) 12 34 5S 01 23 45 00 0S

Le prime quattro istruzioni sono esattamente le stesse dell'esempio precedente, tranne per il fatto che
And Immediate sostituisce la Move Numeric. L'istruzione finale ora è uno spostamento con offset che
sposta la posizione di una cifra a destra.
DIVISIONE DECIMALE CON SHIFTING
Ora siamo pronti ad affrontare un problema realistico relativo alla divisione decimale. Supponiamo che
in un campo di quattro byte denominato SUM abbiamo il totale del numero di ore lavorate da tutti i
dipendenti di una fabbrica, espresso in decimi di ora. In NUMBER abbiamo il numero dei dipendenti
compresi nella somma; questo è un numero a due byte. Dobbiamo calcolare la settimana lavorativa
media, in decimi di ora, arrotondata e inserirla in una posizione a due byte denominata AVERAG.

Iniziamo l'analisi del problema sapendo che il dividendo (SUM) ha una cifra decimale iniziale e il divisore
(NUMBER) non ne ha nessuna. Se impostassimo la divisione in questo modo, otterremmo un quoziente
di una posizione; ciò non consentirebbe l'arrotondamento. Evidentemente dovremo concedere posizioni
extra a destra. Sarebbe sufficiente una in più, ma ciò comporterebbe uno spostamento di un numero
dispari di posizioni; sarebbe più semplice per noi e più veloce nella macchina effettuare uno
spostamento di due posizioni e ignorare semplicemente la cifra in più. Il dividendo quindi dovrebbe
essere così impostato:

XX XX XX X0 0+
Le X rappresentano qualsiasi cifra.

Ora passiamo alla regola secondo cui il numero di byte nel dividendo è uguale al numero di byte nel
divisore più il numero di byte nel quoziente. Sappiamo che abbiamo due byte nel divisore. Il quoziente
deve essere massimo tre: non possono esserci più di due cifre prima della virgola decimale, ce ne
saranno tre dopo la virgola decimale e ci sarà un segno. (Ci saranno tre cifre decimali nel quoziente
perché ce ne sono tre nel dividendo e nessuna nel divisore.)

Il dividendo evidentemente dovrebbe essere di cinque byte. In realtà, cosa che non sarà sempre così,
tale sarà il risultato dello shifting che abbiamo deciso. Fatte queste premesse, diamo ora un'occhiata al
programma mostrato nella Figura 5-6. Partiamo dal presupposto che sia lecito distruggere il contenuto
originale di SUM; se così non fosse, sarebbe questione di un'istruzione aggiuntiva per spostare il
contenuto di SUM in una posizione di memoria adeguata.

Figura 5-6. Programma assemblato che mostra divisione decimale e "shifting". I risultati passo passo
previsti durante l'esecuzione sono inclusi nel campo dei commenti.

Potrebbero piacerti anche