4
di Pierluigi Panunzi Il set di istruzioni ISTRUZIONI DI CONTROLLO Il A partire da questa puntata affronteremo l'analisi dettagliata delle istruzioni che consentono di effettuare un completo controllo sulla programmazione ed in particolare sul flusso di istruzioni: parleremo infatti delle istruzioni di salto, condizionato e non, delle chiamate a subroutine e successivi ritorni al programma chiamante, e delle istruzioni di controllo dei loop. Per i nostri lettori non si tratta certo di novità in quanto da un lato, nei vari esempi riportati nel corso delle varie puntate, abbiamo più volte incontrato tali tipi di istruzioni, senza dubbio indispensabili in un qualsiasi programma che si rispetti e di una certa complessità; d'altro canto poi tali istruzioni in generale ricalcano analoghe istruzioni presenti in un qualsiasi microprocessore e che in un certo senso ne rappresentano il «corredo». Nel caso del/'Assembler 8086/88 si ritroveranno ancora una volta argomentazioni relative alla particolare gestione della memoria detta «a segmenti» ed alla dualità «segment-offset» .• Le istruzioni di controllo - JMP Come è universalmente noto, anche da chi è alle prime armi nel campo della programmazione, un'istruzione di salto (la «JMP» per l'appunto, che sta per «JuMP») consente di alterare la naturale caratteristica di sequenzia- lità di esecuzione di un qualunque programma, forzando l'esecuzione di istruzioni poste in un qualsiasi punto della memoria, invece di quelle imme- diatamente successive: ciò potrà avve- nire in maniera «diretta» oppure «in- diretta». Analizziamo dapprima il caso di salti «diretti». In questo caso il programmatore in- dicherà il punto a cui saltare mediante un'etichetta e così il programma salte- rà «direttamente» alla nuova locazio- ne. L'assemblatore tradurrà opportuna- mente il «nome» dell'etichetta a cui saltare in modo tale che poi il micro- processore, all'atto dell'esecuzione stessa del programma, salti effettiva- mente all'istruzione desiderata e cioè all'indirizzo voluto. Il meccanismo di «traduzione» eti- chetta-indirizzo fisico, come diceva- mo, è strettamente legato alla gestione segmentata della memoria e dipende in maniera particolare dal fatto che l'etichetta di arrivo può o meno appar- tenere al segmento «attuale», quello in cui il microprocessore ha eseguito le ultime istruzioni: a seconda infatti che l'etichetta si trovi nello stesso seg- mento oppure in un altro si avrà una differente codifica prima e una diffe- rente esecuzione poi. Supponiamo dunque innanzi tutto che l'etichetta si trovi all'interno dello stesso segmento dell'istruzione «JMP» considerata: si avrà ad esempio una si- tuazione simile CODE SEGHENT AlFA: HOV AL. 33H o •• ·JHP ALFA CODE ENDS nella quale l'etichetta si trova «prima» dell'istruzione di salto, oppure una si- tuazione del tipo CODE SEG!1ENT JHP BETA BETA. CHP BX. CX CODE ENDS in cui il «target» (letteralmente il «ber- saglio», come si dice in gergo) si trova 154 MCmicrocomputer n. 65 - luglio/agosto 1987

set di istruzioni ISTRUZIONI DI CONTROLLO - Giornalista IT · differente codifica prima e una diffe-rente esecuzione poi. ... CODE1 [NDS COOEZ SEGHENT LONTANA lA8EL FAR CODE2 [NOS

  • Upload
    vanhanh

  • View
    218

  • Download
    0

Embed Size (px)

Citation preview

di Pierluigi Panunzi

Il set di istruzioniISTRUZIONI DI CONTROLLOIl A partire da questa puntata affronteremo l'analisi dettagliata delle istruzioni che consentono

di effettuare un completo controllo sulla programmazione ed in particolare sul flusso diistruzioni: parleremo infatti delle istruzioni di salto, condizionato e non, delle chiamate a subroutinee successivi ritorni al programma chiamante, e delle istruzioni di controllo dei loop.Per i nostri lettori non si tratta certo di novità in quanto da un lato, nei vari esempi riportati nelcorso delle varie puntate, abbiamo più volte incontrato tali tipi di istruzioni, senza dubbioindispensabili in un qualsiasi programma che si rispetti e di una certa complessità; d'altro canto poitali istruzioni in generale ricalcano analoghe istruzioni presenti in un qualsiasi microprocessore e chein un certo senso ne rappresentano il «corredo».Nel caso del/'Assembler 8086/88 si ritroveranno ancora una volta argomentazioni relative allaparticolare gestione della memoria detta «a segmenti» ed alla dualità «segment-offset» .•

Le istruzioni di controllo - JMPCome è universalmente noto, anche

da chi è alle prime armi nel campodella programmazione, un'istruzionedi salto (la «JMP» per l'appunto, chesta per «JuMP») consente di alterarela naturale caratteristica di sequenzia-lità di esecuzione di un qualunqueprogramma, forzando l'esecuzione diistruzioni poste in un qualsiasi puntodella memoria, invece di quelle imme-diatamente successive: ciò potrà avve-nire in maniera «diretta» oppure «in-diretta».

Analizziamo dapprima il caso disalti «diretti».

In questo caso il programmatore in-dicherà il punto a cui saltare medianteun'etichetta e così il programma salte-rà «direttamente» alla nuova locazio-ne.

L'assemblatore tradurrà opportuna-mente il «nome» dell'etichetta a cui

saltare in modo tale che poi il micro-processore, all'atto dell'esecuzionestessa del programma, salti effettiva-mente all'istruzione desiderata e cioèall'indirizzo voluto.

Il meccanismo di «traduzione» eti-chetta-indirizzo fisico, come diceva-mo, è strettamente legato alla gestionesegmentata della memoria e dipendein maniera particolare dal fatto chel'etichetta di arrivo può o meno appar-tenere al segmento «attuale», quelloin cui il microprocessore ha eseguitole ultime istruzioni: a seconda infattiche l'etichetta si trovi nello stesso seg-mento oppure in un altro si avrà unadifferente codifica prima e una diffe-rente esecuzione poi.

Supponiamo dunque innanzi tuttoche l'etichetta si trovi all'interno dellostesso segmento dell'istruzione «JMP»considerata: si avrà ad esempio una si-tuazione simile

CODE SEGHENT

AlFA: HOV AL. 33H

o ••

·JHP ALFA

CODE ENDS

nella quale l'etichetta si trova «prima»dell'istruzione di salto, oppure una si-tuazione del tipo

CODE SEG!1ENT

JHP BETA

BETA. CHP BX. CX

CODE ENDS

in cui il «target» (letteralmente il «ber-saglio», come si dice in gergo) si trova

154 MCmicrocomputer n. 65 - luglio/agosto 1987

«dopo» l'istruzione di salto.Abbiamo suddiviso il caso di salto

all'interno dello stesso segmento (det-to «intra-segment jump») nei due sot-to-casi visti in quanto è differente ilcomportamento dell'assemblatore neidue frangenti.

Sottolineiamo a questo punto che inquesti casi l'assemblatore si comportanel modo «più risparmiatore» possibi-le, come già abbiamo visto in altri casi,nel senso che laddove può risparmiareun byte lo fa senza tanti scrupoli.

Analizziamo dunque il primo sotto-caso, nel quale l'etichetta viene defini-ta «prima» delle sue utilizzazioni co-me «target»: in questo caso l'assem-blatore, mano a mano che analizza ilnostro listato sorgente, ad un certopunto incontrerà l'etichetta «ALFA»ed allora, non conoscendola, la memo-rizzerà all'interno di una sua appositatabella interna di riferimento, insiemeall'offset che ha tale etichetta, offsetche nel frattempo, istruzione dopoistruzione, viene correttamente aggior-nato.

Nel caso in cui a questo punto giàtrovasse proprio quell'etichetta all'in-terno della sua tabella, il che significache già c'era stato un punto in cui l'eti-chetta in questione era stata usata perdefinire una locazione di memoria, al-lora segnalerebbe il suo disappuntocon un messaggio di errore che suonacome «etichetta duplicata».

Fatto dunque ciò, l'assemblatorecontinuerà la sua analisi del sorgente,aggiornando istruzione dopo istruzio-ne l'offset corrente: allorché troveràl'istruzione di salto «JMP ALFA»,cercherà all'interno della sua tabellinal'offset corrispondente ed effettueràun calcolo semplicissimo, la differen-za tra l'offset dell'etichetta e quello at-tuale.

Se tale differenza (e qui si innesca ilmeccanismo «economico»), espressain complemento a 2, può essere rap-presentata da un solo byte allora cosìla esprime, mentre in caso contrario laesprime su due byte: in particolare sela differenza tra gli offset, che vienecorrentemente indicata con il termine«displacement», è minore di 127 (sepositiva) o di - 128 (se negativa) allo-ra verrà rappresentata con un byte,che infatti come noto può rappresen-tare in notazione «complemento a 2»un numero compreso tra - 128 e+ 127.

Si parla in tali casi di «direct shortjump» o «salto corto diretto».

In tutti gli altri casi, e cioè per valoridi displacement compresi tra - 32768e +32767, allora la codifica avverrà sudue byte: i lettori preoccupati se in ta-le modo da un'istruzione di salto sipuò raggiungere «qualsiasi» locazioneall'interno del segmento, troverannorisposta nel fatto oramai più che ripe-

tuto che un segmento di per sé è am-pio proprio 65536 byte (64 kbyte) edunque ogni locazione è raggiungibi-le, con un displacement positivo o ne-gativo.

Ovviamente nei due casi in cui il di-splacement è espresso con un solo by-te oppure con due, l'opcode relativosarà completamente differente (cimancherebbe ...): nel caso di «shortjump» l'opcode vale «EBH», mentrenell'altro caso vale «E9H».

Vediamo ora cosa succede nel casoin cui l'assemblatore incontra un'istru-zione di salto, la cui etichetta ancoranon conosca: in tal caso, lungi dal se-gnalare tale fatto con un errore, il no-stro «economo» si comporterà vice-versa in maniera contraria alla sua na-tura, preparando la strada al caso peg-giore e cioè presupponendo che l'eti-chetta posta nell'istruzione abbia undisplacement maggiore di 127 o - 128byte, lasciando perciò lo spazio a duebyte, il cui contenuto verrà poi effetti-vamente calcolato successivamente al-l'atto del «secondo passo».

In tal modo potranno succedere duefatti legati all'effettivo displacementcalcolato: se tale valore potrà essereespresso con due byte allora non suc-cederà nulla di particolare, mentre nelcaso in cui dovrà essere espresso daun byte soltanto, allora il secondo byteinutilizzato verrà riempito con la codi-fica di un'istruzione «NOP» e cioè«90H».

Ancora una volta il programmatorepuò andare incontro all'assemblatorefornendogli l'indicazione se l'etichettache dovrà ancora individuare si trovao no a meno di 127 byte dall'istruzionedi jump.

In particolare se si presuppone chela locazione sarà «vicina», allora inve-ce di «JMP BETA» si potrà scrivere

JMP SHORT SETA

al che il nostro solerte assemblatore ri-serverà per il displacement solamenteun byte (visto che così gli abbiamodetto noi), ed in caso che tale scelta ri-sulti poi errata allora il «nostro» ci co-municherà che l'etichetta non può es-sere raggiunta (s'intenda «con un di-rect-short-jump» ).

Ciò può essere utile in quei casi incui dobbiamo mantenere il nostro pro-gramma all'interno di una zona benprecisa e perciò dobbiamo contare ibyte utilizzati e risparmiarli di conse-guenza.

Altro tipo di salto diretto è quelloche viene denominato «inter-segmentdirect jump», in gergo «salto lungo olunghissimo» che si ha quando l'eti-chetta a cui si salta e l'istruzione disalto si trovano in due segmenti diffe-renti, ad esempio in un programmadel tipo

ASSEMBLER 8086/8088

CODE l 5EGI1ENT

JI1f> FAR PTR LONTANA

CODE1 [NDS

COOEZ SEGHENT

LONTANA lA8EL FAR

CODE2 [NOS

Vediamo innanzitutto che in questocaso il fatto che l'istruzione di JMP sitrovi «fisicamente» prima della defini-zione dell'etichetta è un fatto pura-mente accessorio, in quanto bastereb-be definire dapprima il segmento CO-DE2 e poi CODEI per aversi la defini-zione dell'etichetta prima dell'istruzio-ne di salto che la interessa: questo perdire che nel caso di salto inter-seg-ment poco importa l'ordine di «appa-rizione» della definizione o dell'«uti-lizzazione» di una certa etichetta.

In particolare l'assemblatore in ognicaso deve trovarsi a che fare con un'e-tichetta di tipo «FAR» e cioè apparte-nente ad un differente segmento, (con-trapposta alle etichette «NEAR» ap-partenenti allo stesso segmento) e per-ciò allorché ne incontrerà la definizio-ne, non la memorizzerà più nella ta-bella precedentemente vista, ma inun'altra tabella appunto riservata alleetichette di tipo «FAR» delle quali ol-tre al nome memorizzerà l'offset ed ilsegment completo.

Analogamente incontrando un'istru-zione di JMP relativa ad un'etichetta«FAR» subito saprà di dover lasciarein ogni caso quattro byte, due per l'off-set e due per il segment: se già avevaincontrato l'etichetta, allora tali 4 bytesaranno subito riempiti, mentre in ca-so contrario si aspetterà il «secondopasso».

In questo caso si vede dunque che'l'assemblatore non si comporta in ma-niera differente a seconda se si incon-tra prima l'etichetta o la JMP, ed inogni caso tradurrà la «JMP» stessacon il codice «EAH».

Vediamo ora dal punto operativocosa farà il microprocessore quandoincontra sul suo cammino un'istruzio-ne di «JMP» (un codice operativo«E9H», «EBH» o «EAH» rispettiva-mente seguiti da 1,2 o 4 byte): nel pri-mo caso (<<intra-segment direct shortjump») sommerà al valore attuale del-l'IP (<<Istruction Pointer») il valoreespresso dal byte di displacement,estendendolo però a 16 bit.

Nel secondo caso (si chiama sempli-cemente «intra-segment direct jump»)all'offset attuale sommerà il valore a16 bit espresso dal displacement, sen-

MCmicrocomputer n. 65 - luglio/agosto 1987 155

REA D CODE SEGf'tENTREAD ~

ENDS

SEGHENT

000

DW READDW SEG READDW WRITEDW SEG WRITEDW RESETDW SEG RESET

HOV BL,ALHOV BH,DSHL 8X. 1SHL 8X,lJHP DWORD PTR TA8ELLA[8XJ

~OUTINE.

TABELLA

CODE

CODE

RESET _ CODE SEGI1ENTRESET:

In questo esempio la tabella conter-rà sia gli offset che i segmenti delle

WRITE_CODE SEGHENTWRITE:

come pureJMP BX

mentre viceversa non sono possibilisalti relativi a registri di segmento: inparticolare l'ultimo esempio, a diffe-renza dell'ultimo del lotto precedente,si «legge»: «salta alla locazione di me-moria il cui offset è contenuto nel regi-stro BX», mentre nel caso precedenteBX forniva l'indirizzo della cella dimemoria all'interno del quale trovarel'offset a cui saltare.

Abbiamo detto che sono possibilianche gli «inter-segment indirectjump»: questi si ottengono soltanto at-traverso locazioni di memoria e nonsono possibili attraverso registri (chedovrebbero in questo caso essere presiin coppia).

In questo caso dunque si avrà a chefare con locazioni di memoria che perloro natura saranno delle «double-word» o più comodamente con coppiedi «word» dove comunque i primi duebyte devono contenere l'offset dellalocazione ed i successivi due byte ilsegmento di appartenenza.

Volendo estendere l'esempio prece-dente a routine appartenenti a seg-menti completamente differenti, otte-niamo un programma che è modifica-to cosÌ:

Nel caso invece in cui come operan-do dell'istruzione di JMP compaia unregistro, allora il suo contenuto saràl'offset dell'etichetta a cui saltare, co-me visto nel caso precedente: si po-tranno avere casi del tipo

JMP exJMP AXJMP BPJMP SP

CODE SEGHENT

TABELLR DW REA ODW WRITEDW RESET

ROUTINE; HOV BL,ALHOV 8H,OSHL BX. lJHP TABELLA[BX]

;READ.

WRITE:

;RESET;

CODE ENDS

JKP [ex]

J"P ETICHETTA ; attenzione ETICHETTAe' una cella!

JKP TABlHBX]JKP ALFIUBP][SI+,5]

come pure

In questo esempio vediamo che ilvalore contenuto in AL viene posto inBL, dopodiché viene costruito un va-lore a 16 bit in BX, che viene poi mol-tiplicato per due per fornire un indiceall'interno della tabella di indirizzichiamata appunto «TABELLA».

In questo caso l'assemblatore, all'at-to della codifica dell'istruzione di sal-to, troverà nel campo riservato all'eti-chetta il nome di una variabile, conl'aggiunta del registro BX come indi-ce: a questo punto saprà trattarsi di unsalto indiretto e codificherà in un'altramaniera ancora l'istruzione.

Nel caso in cui si tratti di una loca-zione di memoria, potremo dunqueavere tutti i casi possibili di indicizza-zione attraverso registri indice e regi-stri base, con o senza offset aggiunti vi,ben noti in quanto tipici dell'Assem-bler 8086/88: alcuni esempi sono

In tutti questi casi l'offset a CUI SIsalterà sarà rispettivamente contenutonella locazione chiamata subdolamen-te «ETICHETTA», in una locazioneall'interno della tabella «TABLE» (aseconda del valore di BX), in una lo-cazione posta all'interno della tabella«ALFA» a seconda del valore con-giunto del contenuto del registro BP(il che obbliga la tabella ad essere resi-dente nello Stack Segment, ricordate?)e del contenuto di SI aumentato di 5ed infine nella locazione il cui offset èposto in BX.

In particolare quest'ultima istruzio-ne (<<JMP (BX]») si legge: «salta all'i-struzione il cui offset è contenuto nel-la cella di memoria il cui offset è postonel registro BX». Lasciamo al lettore ilcompito di «leggere» la penultimaistruzione ...

za ulteriori problemi e, come nel casoprecedente, salterà all'istruzione aven-te tale offset.

Nel terzo caso (<<inter-segment di-rect jump») invece il microprocessoreassumerà i primi due byte come valorenuovo per l'IP ed i successivi 2 bytecome nuovo CS (<<Code Segment»),senza effettuare cioè calcoli di sorta,ma semplicemente impostando nuovivalori ai due registri IP e CS: a questopunto il salto all'etichetta «FAR» de-siderata è puramente automatico, ..

Fin qui abbiamo parlato di salti «di-retti», quelli cioè in cui siamo noi aporre direttamente nell'istruzione l'eti-chetta a cui vogliamo che il micropro-cessore salti.

I salti indirettiIn questo caso l' «indirettezza» con-

siste nel fatto che l'etichetta a cui sal-tare non è esplicitamente indicata nel-l'istruzione, ma bensÌ è raggiungibileindirettamente attraverso il contenutodi una locazione di memoria o di unregistro.

Si parlerà, nel caso di salti indiretti,solamente di «intra-segment indirectjump» o di «inter-segment indirectjump» a seconda che l'etichetta daraggiungere rispettivamente apparten-ga o meno allo stesso segmento di cuifa parte l'istruzione di salto: in questocaso mancano i «short jump» ed oravedremo subito il perché.

Iniziamo dalle istruzioni di salto in-diretto all'interno di un segmento: intal caso non si avrà più a che fare conun displacement (che potrebbe stare inuno o due byte), ma bensÌ si ha a chefare con valori assoluti dell'offset del-l'etichetta a cui si deve saltare.

Dal momento che dunque abbiamoa che fare con un offset «vero» (e per-ciò non da calcolarsi), nasce sponta-nea la possibilità di salvarlo all'inter-no di un registro o di una cella di me-moria di tipo «WORD» per poi salta-re indirettamente all'etichetta.

L'utilizzazione migliore di un'istru-zione di salto indiretto è la traduzionea bassissimo livello di un'istruzione«CASE» del Pascal o di una «ON xGOTO ...» del Basic e cioè tutte quelleoccasioni in cui, in base al valore «n»di una certa variabile, si debba saltareali' «n-esima» etichetta di una certa ta-bella di etichette.

Supponiamo per esempio di scrive-re una routine di gestione di un'unitàa dischi, per la quale, in base al valorecontenuto nell'accumulatore, si possaeffettuare una differente operazione,ad esempio una lettura da disco, unascrittura verso il disco o il reset dell'u-nità a dischi.

Un esempio di frammento di pro-gramma che gestisce il tutto è il se-guente

ASSEMBLER 8086/8088

Il

156 MCmicrocomputer n. 65 - luglio/agosto 1987

routine, per un totale ogni volta di 4byte e perciò BX deve essere moltipli-cato per 4; inoltre nell'istruzione disalto bisognerà indicare che la locazio-ne da cui prelevare l'indirizzo comple-to è una «double-word» (DWORDPTR) in quanto un'istruzione «JMPTABELLA[BX)>> è riferita ad un saltointra-segment dal momento che «TA-BELLA» è definita di tipo «WORD»e non «DWORD».

Dunque come regola l'assemblatoregenererà, in caso di indirizzamento in-diretto, un salto «intra-segment» se lavariabile è di tipo «WORD» oppureun salto «inter-segment», se di tipo«DWORD»: in quest'ultimo caso, ladirettiva «DWORD PTR» serve ad ag-giustare le cose se la variabile è di tipo«WORD».

Dal momento che con la direttiva«LABEL» possiamo definire ad esem-pio «DWORD» ciò che è «WORD»,ecco che il programma in esame si po-trebbe scrivere pure in questo modo

CODE SECI'lENT

TRB DD LA8EL DWORDTABELLA OW READ

DW SEC READDW WRITEow SEe WRITEDW RESETDW SEC RE5ET

ROUTIHE: l'lOV BL,AL"OV 8H,OSHL 8X.1SHL 8X,1j"P TAS_DOCeX]

CODE [NOOS

dove appunto TAB_DD è proprio ditipo «DWORD».

Analogamente al caso dell' «intra-segment indirect jump», però a pattoche la locazione a cui si fa riferimentosia di tipo (esplicitamente o implicita-mente) «DWORD», sono consentiteistruzioni del tipo

J"P OWOROTAB[BX]CSI+l]J"P DWORD PTR ALFA(BP-4]

come pure

.mp DWORO PTR [ex]

dove in quest'ultimo caso si salterà al-l'istruzione il cui indirizzo completo èposto nella double-word (all'internodel Data Segment, non dimentichia-mocelo ...) il cui offset è posto all'inter-no del registro BX.

Terminiamo l'analisi dell'istruzioneJMP con la considerazione che in tutti

ASSEMBLER 8086/8088

i casi in cui si ha un salto indiretto attra-verso una locazione di memoria espli-cita o implicita, valgono le considera-zioni relative al cosiddetto «SegmentOverride», secondo il quale (lo ricor-diamo) un riferimento ad una locazio-ne appartenente ad un certo segmentoper default, può essere «scavalcata»dall'indicazione di un altro segmento.

Infatti, se supponiamo che la nostratabella di salti (indiretti o diretti chesiano) sia posta all'interno del CodeSegment (è il caso di programmi chegireranno su EPROM, ad esempio),allora per indirizzare correttamente ta-le tabella, bisogna effettuare l' «overri-de» indicando esplicitamente il regi-stro CS.

Riprendendo l'ultimo esempio, se latabella TAB_DD fosse posta nel CodeSegment, allora bisogna scrivere

JMP CS:TAB_DD[BX)

dal quale ancora una volta si vedequali e quante possibilità ci offre que-sto assemblatore.

Nella prossima puntata continuere-mo il discorso sulle istruzioni di saltoed in generale sulle istruzioni di con-trollo, forzatamente interrotto a que-sto punto per mancanza di spazio.

Me

m\\\\\\

ITALLGRASSTECHNOLOGIESCOMMITTEDlO MEHOV:f

MCmicrocomputer n. 65 - luglio/agosto 1987

Standard PCITper scambio dati• Potente sistema di correzione d'errore• Facilità d'uso - comandi tipo DOS• Elevata affidabilità• Indirizzabile come unità disco• Montaggio interno o esterno

SISTEMI INTEGRATIVIPER PERSONAL COMPUTER

VIA FlLOM.NO, Il nL (01) 838lII5I • 8380401 • TU 120238 • 001. IIIMAVIA NICOURDI, 121 • nL (011) 1434717 • 80131 NAPOU

157