Assembly VI

[La logica di presentazione degli argomenti di questo modulo si ispira a Linguaggio Assembly per pc IBM di Peter Norton]

Assemblatore

L'assemblatore e' un programma che consente di assemblare il codice mnemonico assembly trasformandolo, con l'ausilio di altri programmi, in codice eseguibile dalla macchina. A differenza di debug per cui tutti i numeri erano di default esadecimali, l'assemblatore assume che tutti i numeri, salvo indicazione contraria, siano decimali.

code_seg

segment  
  mov ah, 2h    
  mov dl, 2ah    
  int 21h    
  int 20h    
code_seg   ends  
  end    

Queste istruzioni andranno scritte mediante un programma di videoscrittura privo di formattazione tipo txt. E' sconsigliabile utilizzare word o altri programmi di videoscrittura che impostano automaticamente la formattazione del testo.
Il programma scritto sopra lo avevamo visto nel modulo II. Anche in quella occasione era stato specificato l'esadecimele per i numeri [h] ma dal momento che andavamo a scrivere su debug h non era necessaria. Ora per l'assemblatore questa specifica e' assolutamente necessaria altrimenti 2, 2a, 21 e 20 verrebbero letti come numeri decimali provocando errore. Un ulteriore accorgimento deve essere messo in pratica quando ci si accinge a scrivere numeri esadecimali come questo: fah. Questo infatti potrebbe essere confuso per un'etichetta e quindi davanti dovremo porre uno zero [0] per specificare all'assemblatore che si tratta di un numero [0fah].
Le istruzioni code_seg segment, code_seg ends e end, non sono proprio istruzioni; esse vengono definite pseudooperazioni perche' in realta' esse non si riferiscono al codice, non aggiungono istruzioni al codice, ma parlano all'assemblatore defininedo alcune specifiche del suo modo di operare.
Scritto il codice, esso va nominato con estensione .asm [ad esempio aster.asm]. Il file asm va inserito nella cartella di windows, dove e' contenuto l'assemblatore MASM . Ora va aperta la shell di DOS. Da DOS ci si puo' accertare del contenuto del programma digitando type aster.asm che listera' tutto il codice contenuto nel file.
Ora scriviamo:

masm aster;

   

Quello che otterremo e' un file cosiddetto oggetto [.obj]. Ora il programma va correlato mediante il linker. Ad essere correlato deve essere questa volta il file oggetto;

link aster;

   

Nel caso del programma preso come esempio, il linker riportera' la presenza di un errore nell'assenza del segmento di stack [che vedremo piu' avanti]. In questo caso si puo' evitare di considerare significativo questo messaggio e proseguire. Il linker ha prodotto un file .exe [un file eseguibile].
L'ultimo procedimento da realizzare prima di avere un programma funzionante [secondo il tipo di istruzioni scritte] e' quello di trasformare il nostro exe in un file .com. Se infatti avessimo voluto creare un file exe funzionante avremmo dovuto utilizzare delle istruzioni leggermente diverse nel nostro programma. Per trasformere un file exe in un file com dobbiamo utilizzare l'utility exe2bin. Questa sigla significa letteralmente exe to bin e serve appunto a convertire un file exe in un file binario; qui il comando e' leggermente diverso da quelli visti in precedenza:

exe2bin aster aster.com

   

Digitare ora aster.com per lanciare la nostra versione com del programma.
Il programma dovrebbe stampare un asterisco sullo schermo del monitor.
Per mezzo del masm possiamo assemblare programmi con etichette [invece delle locazioni di memoria utilizzate con debug] e inoltre sara' possibile inserire i commenti dopo il punto e virgola. Risultera' cosi' piu' agevole lavorare con i programmi perche' per apportare delle modifiche sara' sufficienete riaprire il file di testo originario, procedere ai cambiamenti e riassemblare il tutto nel modo sopra descritto.

Procedure

Riprendiamo il programma visto nell'ultimo modulo e trasformiamolo in un programma leggibile dall'assemblatore:

code_seg

 

segment
assume cs:code_seg
  org 100    
asc proc near  
  call inizio   ; le istruzioni sono spiegate nel modulo precedente
  mov dl, al  
  mov cl, 04h  
  shl dl, cl    
  call inizio  
  add dl, al  
  mov ah, 02h    
  int 21h    
  int 20h    
asc endp    
     
asc1 proc near  
inizio:      

push dx    
mov ah,08h  
nuovo:    
  int 21h    
  cmp al, 30h  
  jb nuovo  
cmp al, 46h  
  ja nuovo  
cmp al, 39h    
ja lettera    
mov ah, 02h    
mov, dl, al    
int 21h    
  sub al, 30h    
  pop dx    
  ret    
lettera:      
  cmp al, 41h    
  jb nuovo    
  mov ah, 02h    
  mov dl, al    
  int 21h    
  sub al, 37h    
  pop dx    
  ret    
asc1 endp    
code_seg ends  
end asc  

E' possibile scaricare il file asc.zip contenente il sorgente asm, del programma chiamato asc.com scritto sopra.
Per la spiegazione delle istruzioni rimandiamo al modulo precedente. Qui ci occuperemo di esaminare le procedure.

- Segment segnala all'assemblatore in quale segmento di memoria andare a scrivere il codice. Nel nostro caso il codice di segmento interessato e' il CS [Code Segment] ma l'8088 ha la possibilita' di identificare 4 segmenti e quindi 4 registri: DS [Data Segment], SS [Stack Segment], ES [Extra Segment]. Questi registri verranno esaminati in seguito. Attenzione: code_seg e' nella colonna delle etichette perche' e' un'etichetta.
- Assume e' una pseudooperazione che da informazioni all'assemblatore sui segmenti e su i registri loro annessi. Nel nostro esempio, assume cs:code_seg indica all'assemblatore che il registro CS deve puntare al segmento chiamato code_seg.
- Near indica all'assemblatore che le chiamate che verranno effettuate, come ad esempio da una call, sono limitate ad un segmento lungo 64k. Per programmi piu' lunghi dovra' essere utilizzata la pseudooperazione far.
Il nostro programma e' racchiuso tra segment e ends; l'end finale serve per segnalare all'assemblatore non solo la fine della procedura, ma dell'intero codice. Qualsiasi cosa sara' scritta dopo l'end non verra' presa in considerazione. Inoltre il programma e' composto da due procedure: esc che e' la procedura principale entro cui tutto il programma ha luogo e esc1 che e' la procedura secondaria; a ben vedere questa divisione in procedure ricalca la divisione in due tronchi del programma che avevamo gia' visto quando esso era stato scritto per debug.
Ulteriori chiarimenti sulle procedure emergeranno nei moduli successivi dove sara' specificato ulteriormente il motodo di indirizzamento della memoria del 8088. Vale la pena chiarire subito che lo studio della segmentazione della memoria dell'8088 ha un valore puramente didattico [se non addirittura archeologico] visto che le cpu piu' recenti lavorano con una architettura della memoria completamente differente. E' comunque possibile lavorare come se ci trovassimo alle prese con una cpu 8086-8088 perche' le cpu piu' recenti [a partire dalla 80286] creano una macchina virtuale 8086 costituita da un'area di memoria virtuale da 1 Mb su cui far girare programmi per DOS senza lasciare il sistema operativo.

torna a modulo V  
 
 

Assembly modulo VI l'assemblatore e le sue procedure.