Professional Documents
Culture Documents
ΣΧΟΛΗ ΜΗΧΑΝΙΚΩΝ
ΤΜΗΜΑ ΗΛΕΚΤΡΟΛΟΓΩΝ & ΗΛΕΚΤΡΟΝΙΚΩΝ ΜΗΧΑΝΙΚΩΝ
Αθήνας 2018
2
Περιεχόμενα
1. Διευθυνσιοδότηση μνήμης
2. Ο σωρός (stack)
3. Προγραμματισμός σε Assembly
ΠΑΡΑΡΤΗΜΑ Α
1 Κατηγορίες Εντολών
ΠΑΡΑΡΤΗΜΑ Β
ΠΑΡΑΡΤΗΜΑ Γ
ΠΑΡΑΡΤΗΜΑ Δ
Θεωρητικό Υπόβαθρο
1 Διευθυνσιοδότηση μνήμης
Ο 8086 έχει 20 γραμμές διευθύνσεων, άρα μπορεί να προσπελάσει άμεσα μέχρι 220 =
1Μ θέσεων μνήμης (θυμίζουμε ότι 1Μ=1.048.576). Η χαμηλότερη θέση έχει
διεύθυνση 00000Η και η υψηλότερη FFFFFH. Η κάθε θέση μνήμης έχει
χωρητικότητα 1byte (8 bits).
Ο συμβολισμός DS:AX παριστάνει την φυσική (20μπιτη) διεύθυνση που προκύπτει αν σαν
αρχική διεύθυνση segment θεωρήσουμε το περιεχόμενο του καταχωρητή DS
πολλαπλασιάζοντάς το επί 16 (ή 10Η), έτσι ώστε να γίνει 20μπιτο και μετατόπιση μέσα στο
segment αυτό ίση με το περιεχόμενο του ΑΧ. Άρα ο γενικός κανόνας που ισχύει είναι:
Στο παράδειγμά μας η φυσική διεύθυνση θα είναι 1000Η * 10Η + 0540Η = 10000Η +
0540Η = 10540Η.
Επίσης πρέπει να αναφέρουμε ότι όταν χρησιμοποιείται μόνο ένας καταχωρητής για να
δηλώσει μια διεύθυνση μνήμης, αυτός δίνει πάντα το offset της διεύθυνσης. Καταχωρητής
segment γενικά θεωρείται εξ΄ορισμού ο DS, εκτός και αν έχουμε τους BP ή SP οι οποίοι
συνδυάζονται εξ΄ορισμού με τον SS, ή τον ΙΡ ο οποίος συνδυάζεται με τον CS.
Μια δεύτερη παρατήρηση που πρέπει να γίνει εδώ είναι το ότι τα διάφορα segments δεν είναι
απαραίτητο να είναι ανεξάρτητα μεταξύ τους, αλλά μπορεί να είναι και επικαλυπτόμενα. Για
παράδειγμα, αν ο σωρός ενός προγράμματος καταλαμβάνει
100Η bytes, τα δεδομένα 50Η bytes και το κυρίως πρόγραμμα 200Η bytes, οι αντίστοιχοι
segment registers μπορεί να έχουν τις εξής τιμές: SS=0100H, DS=0200H και CS=0250H.
Ο τρόπος αυτός οργάνωσης της μνήμης μπορεί να φαίνεται περίπλοκος, έχει όμως ένα
μεγάλο πλεονέκτημα. Τα προγράμματά μας μπορούν εύκολα να επανατοποθετηθούν σε
οποιοδήποτε άλλο σημείο της μνήμης ή σε οποιονδήποτε άλλο υπολογιστή (PC), χωρίς
να χρειαστεί να ξαναγραφούν. Το μόνο που χρειάζεται να γίνει είναι να αλλάξουν τιμές οι
τέσσερις segment registers, κάτι που καθορίζεται αυτόματα από το σύστημα και ο χρήστης
δεν έχει να κάνει τίποτα. Όλοι οι υπόλοιποι καταχωρητές δεν χρειάζεται να πειραχθούν, διότι
δεν αναφέρονται σε απόλυτες διευθύνσεις μνήμης, αλλά σε αποκλίσεις μέσα σε κάποιο
λογικό segment.
2. Ο σωρός (stack)
Ο σωρός είναι μια περιοχή της μνήμης RAM στην οποία μπορούμε να
7
αποθηκεύσουμε προσωρινά δεδομένα με την λογική LIFO (last in first out). Αυτό σημαίνει
ότι η πρώτη λέξη που θα επανακτήσουμε από το σωρό θα είναι η τελευταία που
αποθηκεύσαμε. Για αποθήκευση και επαναφορά από τον σωρό χρησιμοποιούνται οι εντολές
PUSH και POP αντίστοιχα. Η διεύθυνση της κορυφής του σωρού είναι η SS:SP. Κάθε φορά
που ρίχνουμε κάτι στο σωρό (με την εντολή PUSH), ο σωρός αυξάνει προς τα πάνω
(χαμηλότερες διευθύνσεις) και το περιεχόμενο του SP μειώνεται κατά 2 Αντιθέτως όταν
επαναφέρουμε με την εντολή ΡΟΡ κάτι από τον σωρό το περιεχόμενο του SP αυξάνει κατά
2. Ο σωρός δηλαδή ακολουθεί αντίθετη λογική από την υπόλοιπη μνήμη, στην οποία
τα δεδομένα γράφονται από χαμηλότερες σε υψηλότερες διευθύνσεις.
Το ανώτερο επιτρεπόμενο μέγεθος του σωρού σε ένα πρόγραμμα περιορίζεται από το μέγεθος
ενός segment, δηλαδή 64 Kbytes. Αν προσπαθήσουμε να ξεπεράσουμε τα 64 Kbytes, δεν
πρόκειται να ξεφύγουμε από το segment του σωρού (stack segment) και να καταστρέψουμε
άλλα τμήματα του προγράμματός μας, διότι όπως είπαμε κάθε segment είναι κυκλικό,
δηλαδή η αρχή του γειτονεύει με το τέλος του. Έτσι, αν ο σωρός έχει συμπληρώσει τα
64Kbytes μεγέθους, τα νέα δεδομένα που θα ριχθούν θα πέσουν πάνω σε αυτά που είχαν
τοποθετηθεί αρχικά.
Παράδειγμα:
3 Προγραμματισμός σε assembly
Στο κεφάλαιο αυτό θα δούμε την χρήση των ευκολιών του assembler (ψευδοεντολές ή
directives), την δομή ενός προγράμματος σε assembly, καθώς και την χρήση των ρουτινών
του BIOS και του DOS για την ανάπτυξη απλών εφαρμογών.
Ο assembler είναι ένα πρόγραμμα που μετατρέπει ένα πρόγραμμα συμβολικής γλώσσας
(assembly) σε γλώσσα μηχανής. Οι πιο δημοφιλείς assemblers για τον 8086 είναι ο MASM
(Microsoft Assembler) και ο TASM (Turbo Assembler). Τα προγράμματα που θα δούμε στην
συνέχεια είναι γραμμένα για τον MASM, αλλά τα περισσότερα από αυτά θα τρέξουν και στον
TASM χωρίς αλλαγές.
Για να δημιουργήσουμε ένα εκτελέσιμο πρόγραμμα πρέπει πρώτα να γράψουμε τον πηγαίο
κώδικα ή κώδικα συμβολικής γλώσσας (assembly). Όπως σε όλες τις γλώσσες
προγραμματισμού, έτσι και στην assembly ο πηγαίος κώδικας πρέπει να είναι ένα αρχείο
κειμένου ASCII του οποίου η προέκταση να φανερώνει από ποια γλώσσα προήλθε. Για την
assembly έχει καθοριστεί η προέκταση των αρχείων του πηγαίου κώδικα να είναι πάντα
.ASM.
Το επόμενο βήμα είναι να περάσουμε το αρχείο από τον assembler, ο οποίος παράγει τον
αντικειμενικό κώδικα (object code). Ο αντικειμενικός κώδικας περιέχει εκτελέσιμο κώδικα
μηχανής και πρόσθετες πληροφορίες σχετικά με την δομή του εκτελέσιμου προγράμματος.
Τα αρχεία αντικειμενικού κώδικα έχουν την προέκταση
.OBJ στο όνομα αρχείου τους.
το πρόγραμμα .COM σε 64 Kbytes μνήμης και τοποθετεί τον σωρό στην κορυφή. Αν λοιπόν
ένα πρόγραμμα είναι κατάλληλο για .COM, μπορούμε να παράγουμε πρώτα το αρχείο .ΕΧΕ
και μετά, με την χρήση της εντολής EXE2BIN που παρέχεται από το DOS, να το
μετατρέψουμε σε .COM. Τα .COM αρχεία καταλαμβάνουν λιγότερο χώρο και φορτώνονται
πιο γρήγορα από τον δίσκο.
Το γεγονός ότι ένα .COM αρχείο μπορεί να χρησιμοποιήσει ένα μόνο λογικό segment,
έχει σαν αποτέλεσμα να μπορεί να τοποθετηθεί οπουδήποτε μέσα στην μνήμη. Αυτό
συμβαίνει διότι χρησιμοποιεί κλήσεις και διακλαδώσεις τύπου NEAR (16μπιτες), άρα
πουθενά μέσα στο πρόγραμμα δεν υπάρχουν απόλυτες διευθύνσεις, παρά μόνο σχετικές.
Αντίθετα, τα .ΕΧΕ προγράμματα, που έχουν πολλά λογικά segments, δεν έχουν την
δυνατότητα να τοποθετούνται οπουδήποτε στην μνήμη. Αυτό εξηγείται ως εξής :
Συνήθως, οι πρώτες εντολές του κυρίως κώδικα ενός προγράμματος είναι οι εξής :
Με αυτές τις εντολές δίνεται στον DS η τιμή της μεταβλητής DATA που την έχουμε ορίσει
νωρίτερα να δείχνει την διεύθυνση του data segment. Η πρώτη εντολή δεν μπορεί να
μεταφραστεί άμεσα από τον assembler. Αυτό γιατί δεν γνωρίζει όταν το λειτουργικό
πρόγραμμα φορτώσει το πρόγραμμα στην μνήμη, σε ποια διεύθυνση θα αντιστοιχεί το
DATA. Το αποτέλεσμα είναι να μην πάρει τιμή ο ΑΧ μέχρι το πρόγραμμα να φορτωθεί
στην μνήμη. Όταν το πρόγραμμα φορτωθεί στην μνήμη, τότε θα πάρει η εντολή τα
δεδομένα που θα φορτωθούν στον καταχωρητή ΑΧ. Η διαδικασία κατά την οποία τα
δεδομένα γεμίζουν, καλείται επανατοποθέτηση (relocation). Οι πληροφορίες για το που
θα πρέπει να τοποθετηθούν τα δεδομένα κατά την φόρτωση του προγράμματος δίνονται
σε μια περιοχή στην αρχή του αρχείου. Όταν το DOS φορτώσει το αρχείο στην μνήμη,
διαβάζει τις διευθύνσεις αυτές και τοποθετεί τα δεδομένα στις θέσεις που πρέπει.
Αναλυτικά, τα βήματα που γίνονται για να εκτελεστεί ένα .COM αρχείο είναι τα εξής:
από την γραμμή εντολής του DOS σαν παραμέτρους στην εκτέλεση του εν λόγω
προγράμματος.
2. Το .COM αρχείο μεταφέρεται από τον δίσκο στην μνήμη αμέσως μετά τον PSP.
3. Όλοι οι segment registers παίρνουν σαν περιεχόμενο την αρχική διεύθυνση του
PSP.
4. O SP παίρνει τιμή FFFEH, δηλαδή η κορυφή του σωρού ορίζεται στο τέλος του
segment. Επίσης δίνεται αυτόματα ένας σωρός μήκους 100Η (256 bytes).
5. O IP παίρνει τιμή 100Η, που σημαίνει ότι το πρόγραμμα αρχίζει από το σημείο αυτό
και κάτω.
Άρα, η δομή ενός .COM προγράμματος όταν αυτό φορτωθεί στη μνήμη είναι:
Τα βήματα που εκτελούνται κατά την φόρτωση για εκτέλεση ενός .ΕΧΕ
προγράμματος είναι τα εξής :
1. Ένα PSP δημιουργείται στην πρώτη ελεύθερη παράγραφο της κύριας μνήμης.
2. Το αρχείο .ΕΧΕ φορτώνεται στην μνήμη από τον δίσκο αμέσως μετά το PSP. To
DOS αναλαμβάνει την επανατοποθέτηση των segments.
3. Οι καταχωρητές DS, ES παίρνουν σαν περιεχόμενο την αρχική διεύθυνση του
PSP.
4. Οι καταχωρητές CS, IP, SS και SP καθορίζονται μέσα από το πρόγραμμα.
Η δομή λοιπόν ενός .ΕΧΕ προγράμματος όταν φορτωθεί στην μνήμη είναι :
11
Όταν γράφουμε ένα πρόγραμμα σε συμβολική γλώσσα πρέπει εκτός από τις εντολές που
μεταφράζονται άμεσα σε γλώσσα μηχανής (εντολές assembly) να δώσουμε και κάποιες
οδηγίες προς τον assembler που έχουν σχέση με τον ορισμό λογικών segment,
τοποθέτηση δεδομένων στην μνήμη, ορισμό μεταβλητών, σταθερών, υπορουτινών,
μακροεντολών, δομών κτλ. Οι οδηγίες αυτές που είναι απαραίτητες για την δημιουργία του
αντικειμενικού κώδικα, λέγονται ψευδοεντολές ή directives και εξαρτώνται από τον
συγκεκριμένο assembler που χρησιμοποιούμε. Στην συνέχεια θα δούμε τις σημαντικότερες
από αυτές.
• Το όνομα δεν πρέπει να συμπίπτει με κάποια από τις δεσμευμένες λέξεις του
assembler, τα directives.
• Αναγνωρίζονται μόνο οι πρώτοι 31 χαρακτήρες.
• Μικρά και κεφαλαία γράμματα δεν διακρίνονται μεταξύ τους.
• Ο πρώτος χαρακτήρας δεν μπορεί να είναι ψηφίο (0-9).
• Ο πρώτος χαρακτήρας μπορεί να είναι η τελεία (.).
Οι μεταβλητές (variables) παίρνουν σαν τιμή δεδομένα της μνήμης και μπορεί να έχουν
μέγεθος 1, 2, 4, 8 ή 10 bytes. Το μέγεθος αυτό καθορίζεται με τις ψευδοεντολές ορισμού
δεδομένων (data definition directives). Με τα directives αυτά μπορεί να
γεμίσει μια περιοχή της μνήμης με δεδομένα, και είναι τα εξής :
Τα ίδια ισχύουν και για τα υπόλοιπα directives, με την διαφορά ότι τα δεδομένα ορίζονται
να έχουν μέγεθος 2, 4, 8 ή 10 bytes αντίστοιχα. Εδώ να υπενθυμίσουμε ότι δεδομένα
μεγαλύτερα από 1 byte αποθηκεύονται στην μνήμη με το χαμηλότερης τάξης byte στην
χαμηλότερη διεύθυνση και το υψηλότερης τάξης byte στην υψηλότερη (μεγαλύτερη)
διεύθυνση.
Παραδείγματα :
όπου εδώ γεμίζουμε 256 (100Η) θέσεις μνήμης με το 41Η (ASCII ισοδύναμο του Α).
Μια σταθερά (constant) μπορεί να πάρει τιμή είτε με το directive EQU, οπότε δεν μπορεί
να αλλάξει τιμή μέσα στο πρόγραμμα, είτε με το directive = , οπότε μπορεί να ξαναοριστεί.
Παράδειγμα :
space1 equ 10
space2 = 12
Τέλος, μια ταμπέλα (label) είναι ένα όνομα που ακολουθείται πάντα από άνω κάτω τελεία
(:), μπορεί να τοποθετηθεί σε οποιοδήποτε σημείο του προγράμματος και αντιπροσωπεύει
την τρέχουσα διεύθυνση του προγράμματος.
Παράδειγμα : L1:
MOV AX, BX JMP
SHORT L1
Μια ταμπέλα μπορεί να συνδυαστεί με το directive LABEL για να του αποδοθεί συνήθως
ο χαρακτηρισμός NEAR ή FAR. Τα directives NEAR, FAR υποδεικνύουν στον assembler
14
αν το συγκεκριμένο όνομα μπορεί να κληθεί μόνο μέσα από το ίδιο segment ή και από
άλλα segments αντίστοιχα. Επίσης, σε εντολές διακλάδωσης μπορεί να χρησιμοποιηθεί
και το directive SHORT που υποδεικνύει στον assembler ότι το άλμα θα είναι short,
δηλαδή από –128 έως +127 θέσεις πάνω ή κάτω (βλέπε και εντολές διακλάδωσης).
Καλύτερη κατανόηση της χρήσης των directives αυτών, καθώς και παρουσίαση κάποιων
ακόμη, θα γίνει όταν θα αναλύσουμε τα πρώτα προγράμματα, αργότερα στο κεφάλαιο.
Υπάρχουν δύο τρόποι για να αναπτύξουμε ένα πρόγραμμα σε assembly: η χρήση έτοιμων
μοντέλων και η πλήρης ορισμός των λογικών segment του προγράμματος.
Στην περίπτωση αυτή η δομή του προγράμματος επιλέγεται μέσα από κάποια
προκαθορισμένα πρότυπα ή μοντέλα που παρέχει ο MASM. Αυτά επιλέγονται με
χρήση του directive .MODEL και μπορεί να είναι τα εξής :
ΜΟΝΤΕΛΟ ΠΕΡΙΓΡΑΦΗ
Tiny Όλο το πρόγραμμα, δηλαδή κώδικας, δεδομένα και σωρός
περιέχεται μέσα σε ένα και μόνο segment. Έτσι, το μέγεθος του
συνολικού προγράμματος θα είναι ≤ 64Kbytes.
Small Τόσο ο κώδικας, όσο και τα δεδομένα καταλαμβάνουν το
καθένα από ένα segment.
Medium Ένα data segment , ένα ή περισσότερα code segments.
Compact Ένα code segment, ένα ή περισσότερα data segments.
Large Οποιοσδήποτε αριθμός code και data segment
Huge Ίδιο με Large, αλλά επιτρέπονται και data segments > 64
Kbytes.
Στο πρόγραμμα αυτό βλέπουμε κάποια καινούργια directives. Πρώτα το directive TITLE
δεν κάνει τίποτε άλλο, από το να δίνει ένα όνομα στο πρόγραμμα και μπορεί άνετα να
παραληφθεί. Τα directives .DATA και .CODE ορίζουν τα data και code segment αντίστοιχα,
ενώ το .STACK χρησιμοποιείται για να καθορίσουμε το μέγεθος του σωρού. Στο πρόγραμμά
μας καθορίστηκε ο σωρός να έχει ανώτατο μέγεθος 256 (100Η) bytes.
Στο data segment γεμίζουμε ένα buffer μεγέθους 12 bytes με διάφορα δεδομένα. Η αρχική
διεύθυνση του buffer συμβολίζεται με την μεταβλητή ΜΕS. Συγκεκριμένα, αποθηκεύονται
εκεί οι εξής 12 χαρακτήρες:
'Κ', 'Α', 'Λ', 'Η', 'Μ', 'Ε', 'Ρ', 'Α', '!', 0DΗ, 0AΗ, '$'.
Το κυρίως πρόγραμμα δεν κάνει τίποτα άλλο από το να καλέσει δύο ρουτίνες του DOS
(αυτό γίνεται με το ΙΝΤ 21Η). Η πρώτη ρουτίνα είναι η συνάρτηση 09 (ΑΗ=09), του ΙΝΤ
21Η, η οποία τυπώνει στην οθόνη τα περιεχόμενα ενός buffer, θεωρώντας ότι αυτά είναι
ASCII χαρακτήρες. Το buffer αυτό θεωρείται ότι ξεκινά στην διεύθυνση DS:DX και
17
Η δεύτερη ρουτίνα που καλεί το πρόγραμμα είναι η ρουτίνα εξόδου στο DOS, η οποία
είναι η συνάρτηση 4CH (ΑΗ=4CH) του ΙΝΤ 21H. Η ρουτίνα αυτή είναι υποχρεωτικό να
υπάρχει στο τέλος κάθε προγράμματος, αλλιώς χάνουμε τον έλεγχο του υπολογιστή. Ας
θυμηθούμε εδώ ότι το MS-DOS ελέγχει τα διάφορα περιφερειακά, όπως το
πληκτρολόγιο και την οθόνη.
Η χρήση των μοντέλων στον προγραμματισμό παρέχει την δυνατότητα να γράφουμε γρήγορα
μικρά προγράμματα, γλιτώνοντάς μας από τον κόπο του αναλυτικού καθορισμού του κάθε
λογικού segment. Έχει όμως το μειονέκτημα ότι πολλά από τα directives που είδαμε δεν
αναγνωρίζονται από όλους τους assemblers (ούτε καν και από τις αρχικές εκδόσεις του
MASM). O TASM για παράδειγμα χρησιμοποιεί τα μοντέλα με λίγο διαφορετικό τρόπο.
Επίσης ο τρόπος αναλυτικού καθορισμού των διαφόρων segments παρέχει καλύτερο έλεγχο
του προγράμματος, και συνήθως προτιμάται, ιδιαίτερα μάλιστα σε μεγάλες εφαρμογές.
;-----------------------------------------
; σωρός
;-----------------------------------------
STACK ENDS
18
;-----------------------------------------
; δεδομένα
;-----------------------------------------
DATA SEGMENT
DATA ENDS
;---------------------------------------------
; κώδικας
;---------------------------------------------
CODE SEGMENT
;-----------------------------
; αρχικές συνθήκες
;-----------------------------
MAIN:
ASSUME CS:CODE
;-----------------------------
; κυρίως κώδικας
;-----------------------------
MOV AH, 09
LEA DX, MES
INT 21H ;εκτύπωση μηνύματος στην οθόνη
CODE ENDS
END MAIN ;τέλος προγράμματος
19
Ένα επίσης νέο στοιχείο είναι το directive THIS το οποίο αντιστοιχίζει την
μεταβλητή STACK_TOP στην τρέχουσα θέση μνήμης, δηλαδή στην κορυφή του σωρού.
Από τα παραπάνω βγαίνει το συμπέρασμα, ότι κάθε πρόγραμμα πρέπει να έχει το εξής
περίγραμμα :
• stack segment
• data segment
• code segment
αρχικές συνθήκες
κυρίως κώδικας έξοδος
στο DOS υπορουτίνες
Κάποιο πρόγραμμα όμως μπορεί να μην έχει data segment, ή αν το πρόγραμμά μας δεν
είναι πολύ μεγάλο, να ορίσουμε ένα λογικό segment τόσο για τα δεδομένα, όσο και για τον
κώδικα. Σε τέτοια περίπτωση θα υπάρχει μόνο stack και code segment, και τα δεδομένα
μπορούν να ορίζονται σε οποιοδήποτε σημείο του code segment (συνήθως τοποθετούνται
στο τέλος). Προσοχή όμως θα πρέπει να δοθεί εδώ στον ορισμό των αρχικών συνθηκών, διότι
θα πρέπει DS=CS.
Το MS-DOS και το BIOS παρέχουν στον χρήστη ένα μεγάλο πλήθος ρουτινών που εκτελούν
πολύ χρήσιμες εργασίες όπως ανάγνωση του πληκτρολογίου, εκτύπωση στην οθόνη και
τον εκτυπωτή, ανάγνωση και εγγραφή σε περιφερειακή μνήμη (σκληρός δίσκος, δισκέτα
κτλ), ανάγνωση και μεταβολή των παραμέτρων του συστήματος και πολλά άλλα. Έτσι
τελικά, ο προγραμματισμός σε assembly ανάγεται σε διαδοχικές κλήσεις ρουτινών (ή
συναρτήσεων) του DOS ή του BIOS και απλή σύνδεση των αποτελεσμάτων. Άλλωστε μια
εφαρμογή, όσο περίπλοκη και αν είναι, μπορεί πάντα να διασπαστεί σε πολλές
απλούστερες εργασίες, οι οποίες θα συνδεθούν κατάλληλα μεταξύ τους.
20
Στο Παράρτημα Β παρέχεται ένας πλήρης κατάλογος των συναρτήσεων του DOS και του
BIOS. Το πλήθος τους είναι τέτοιο, που είναι σχεδόν αδύνατο να τις απομνημονεύσει κανείς.
Το μόνο που χρειάζεται να γνωρίζουμε είναι οι δυο – τρεις συχνότερα χρησιμοποιούμενες,
καθώς και τον τρόπο να διαβάζουμε σωστά τους αντίστοιχους πίνακες.
Μια διακοπή ενεργοποιείται πάντα από μια εντολή ΙΝΤ. Για παράδειγμα η εντολή ΙΝΤ
21H καλεί τις ρουτίνες (συναρτήσεις) του DOS. Οι ρουτίνες αυτές όμως είναι πάρα πολλές.
Το ποια από αυτές θα εκτελεστεί, καθορίζεται από το περιεχόμενο ενός καταχωρητή (του ΑΗ
στην συγκεκριμένη περίπτωση). Η κάθε συνάρτηση είναι μια διεργασία που δέχεται κάποια
δεδομένα σαν είσοδο και βγάζει κάποια άλλα δεδομένα ή εκτελεί μια εργασία σαν έξοδο. Το
τι ακριβώς θα κάνει και από πού θα βρει τα δεδομένα εισόδου (αν χρειάζεται) εξαρτάται από
την ίδια την συνάρτηση.
Η εξ ορισμού συσκευή εισόδου για το DOS είναι το πληκτρολόγιο και εξόδου η οθόνη. Οι
συναρτήσεις 00Η έως 0CH του ΙΝΤ 21H χρησιμεύουν για είσοδο και έξοδο χαρακτήρων
για την εξ ορισμού συσκευή εισόδου/εξόδου CON (κονσόλα).
Κάθε ένας από τους συνηθισμένους χαρακτήρες του πληκτρολογίου, όταν πατηθεί,
δημιουργεί τον αντίστοιχο κωδικό ASCII, ο οποίος τοποθετείται στο buffer που
προαναφέρθηκε. Υπάρχουν όμως και κάποια πλήκτρα, όπως τα πλήκτρα F1-F12, Home, End,
PgUp, Ins, Del, τα βέλη κτλ. τα οποία ονομάζονται πλήκτρα του επεκταμένου
πληκτρολογίου, και δεν αντιστοιχούν σε κάποιο κωδικό ASCII. Η κωδικοποίηση των
πλήκτρων αυτών γίνεται με δύο bytes. Το πρώτο είναι πάντα το
00Η και το επόμενο ονομάζεται scan code και χαρακτηρίζει το συγκεκριμένο πλήκτρο
ή συνδυασμό πλήκτρων (πχ ALT F1). Στους επόμενους πίνακες υπάρχουν οι scan codes για
όλα τα πλήκτρα του επεκταμένου πληκτρολογίου.
End 4F 75
PgUp 49 84
PgDn 51 76
PrtSc 37 72
Left arrow 4B 73
Rt arrow 4D 74
Up arrow 48
Dn arrow 50
Ins 52
Del 53
Back tab 0F
Gray + 4E
Gray - 4A
Η συνάρτηση 01 του ΙΝΤ 21H του DOS αναμένει την είσοδο ενός χαρακτήρα από την
κονσόλα (πληκτρολόγιο) και τον τοποθετεί στον AL. Ταυτόχρονα, ο χαρακτήρας εμφανίζεται
και στην οθόνη (echo), κάτι που μπορεί να δημιουργεί πρόβλημα όταν πληκτρολογούμε για
παράδειγμα ένα password. Οι χαρακτήρες ελέγχου (Enter, Backspace, κτλ) απορρίπτονται.
Στο επόμενο παράδειγμα δίνουμε τιμή σε μια μεταβλητή ονόματι char πατώντας ένα
πλήκτρο.
MOV AH, 1
INT 21H
MOV CHAR, AL
MOV AH, 2
MOV DL, 'A' INT
21H
MOV AH, 5
MOV DL, 'O' INT
21H
MOV DL, 'K'
INT 21H
MOV DL, ODH INT
21H
Ο κωδικός 0DH αντιστοιχεί στον χαρακτήρα ελέγχου carriage return ο οποίος υποδηλώνει
στον εκτυπωτή να εκτυπώσει άμεσα το μήνυμα. Οι περισσότεροι εκτυπωτές τοποθετούν τους
εισερχόμενους χαρακτήρες σε ένα buffer, και τους τυπώνουν όταν το buffer γεμίσει ή όταν
εμφανιστεί το carriage return.
Αν τώρα ο DL δεν είναι FFH, τότε το περιεχόμενο του DL τυπώνεται στην οθόνη. Η επόμενη
ρουτίνα χρησιμοποιεί την συνάρτηση 06H για να καθαρίσει το keyboard buffer.
Η πιο συχνά χρησιμοποιούμενη συνάρτηση του ΙΝΤ 21H είναι η συνάρτηση 09H, η οποία
εκτυπώνει στην οθόνη μια σειρά χαρακτήρων (string). Η διεύθυνση μνήμης όπου βρίσκεται
ο πρώτος χαρακτήρας της σειράς είναι η DS:DX. Η σειρά τελειώνει με τον χαρακτήρα
'$' (24H), ο οποίος όμως δεν εκτυπώνεται. Στο επόμενο παράδειγμα το όνομα ΝΙΚΟΣ
εμφανίζεται στην οθόνη στην αρχή της επόμενης γραμμής.
Η συνάρτηση αυτή διαβάζει μια σειρά χαρακτήρων (string) από το πληκτρολόγιο και τους
τοποθετεί σε ένα buffer. Το πλήθος των χαρακτήρων (μήκος του string) μπορεί να είναι
μέχρι 255. Χαρακτήρες του επεκταμένου πληκτρολογίου (όπως τα βέλη, το PgDn κτλ)
απορρίπτονται, ενώ το τέλος του string δηλώνεται με το ENTER.
Το offset της αρχικής διεύθυνσης του buffer τοποθετείται στον DX. Στην πρώτη θέση μνήμης
πρέπει να τοποθετείται το ολικό μήκος του buffer, στην επόμενη τοποθετεί το DOS το πλήθος
των χαρακτήρων που πληκτρολογήθηκαν, χωρίς να υπολογίσει τον χαρακτήρα ENTER, ενώ
οι υπόλοιπες θέσεις μνήμης θα περιέχουν τους χαρακτήρες αυτούς και το ENTER (0DH).
Το επόμενο παράδειγμα δημιουργεί ένα buffer 50 χαρακτήρων και περιμένει είσοδο από το
πληκτρολόγιο.
BUF_SIZE DB 50
CHAR_BUF DB 51 DUP (0)
.
25
.
.
MOV AX, 0AH
LEA DX, BUF_SIZE INT
21H
Η συνάρτηση αυτή εξετάζει το buffer του πληκτρολογίου για να δει αν βρίσκεται εκεί κάποιος
χαρακτήρας. Αν υπάρχει κάποιος χαρακτήρας, το DOS επιστρέφει FFH στον AL, αλλιώς
επιστρέφει το 00Η.
Η συνάρτηση αυτή καθαρίζει το buffer του πληκτρολογίου και καλεί μια από τις συναρτήσεις
εισόδου κονσόλας, δηλαδή μία από τις 01H, 06H, 07H ή 08H. Ο αριθμός της
συνάρτησης που θα καλέσουμε πρέπει να βρίσκεται στον AL. Στην έξοδο, ο AL θα
περιέχει τον χαρακτήρα που πληκτρολογήσαμε. Το επόμενο παράδειγμα καθαρίζει τον
keyboard buffer, και εισάγει έναν χαρακτήρα στην μεταβλητή ΝΑΜΕ, μέσω της συνάρτησης
07H.
Ένας πιο άμεσος τρόπος για εισαγωγή από το πληκτρολόγιο είναι η χρήση των συναρτήσεων
του ΙΝΤ 16H του BIOS. Στο Παράρτημα Β αναφέρονται όλες αυτές αναλυτικά. Η συνάρτηση
00Η (ΑΗ=0), για παράδειγμα, περιμένει μέχρι να πατηθεί κάποιο πλήκτρο και όταν αυτό
συμβεί, ο αντίστοιχος κώδικας ASCII αποθηκεύεται στον AL. Αν αυτό είναι πλήκτρο του
επεκταμένου πληκτρολογίου, αποθηκεύεται στον AL το 00Η και στον ΑΗ το scan code του
πλήκτρου.
26
Όταν μια εφαρμογή θέλει να τυπώσει κάποιον χαρακτήρα στην οθόνη, έχει δύο επιλογές. Να
γράψει απευθείας στο video buffer ή να χρησιμοποιήσει τις κατάλληλες συναρτήσεις του
ΙΝΤ 10Η του BIOS.
Απευθείας εγγραφή στο video buffer: Το video buffer είναι μια περιοχή της μνήμης στην
οποία είναι τοποθετημένα τα περιεχόμενα της τρέχουσας οθόνης. Η διεύθυνση του video
buffer, το μέγεθός του, καθώς και η κωδικοποίηση των περιεχομένων του, εξαρτάται από
την κάρτα γραφικών που χρησιμοποιούμε και πιθανόν το συγκεκριμένο σύστημα στο
οποίο δουλεύουμε. Τα περιεχόμενα του video buffer διαβάζονται συνεχώς και απεικονίζονται
στα κατάλληλα σημεία της οθόνης. Αν μια θέση μνήμης του video buffer αλλάξει
περιεχόμενο, στην επόμενη ανάγνωση (δηλαδή σε λίγα ms) θα αλλάξει και ο αντίστοιχος
χαρακτήρας (ή pixel αν έχουμε οθόνη γραφικών). Οι εφαρμογές που γράφουν απευθείας
στο video buffer είναι ταχύτατες αλλά δεν μπορούν να λειτουργήσουν το ίδιο σε όλα τα
συστήματα ούτε σε όλους τους τρόπους απεικόνισης (video modes).
Χρήση των ρουτινών του BIOS και του DOS: To INT 10H του BIOS παρέχει αρκετές
συναρτήσεις για απεικόνιση στην οθόνη. Η χρήση τους είναι η ίδια σε όλα τα συστήματα,
αλλά οπωσδήποτε υπάρχει κάποια καθυστέρηση σε σχέση με την απευθείας εγγραφή
στο video buffer. Μπορούν επίσης να χρησιμοποιηθούν και κάποιες ρουτίνες του DOS, αλλά
εκεί η καθυστέρηση είναι μεγάλη.
Γενικές έννοιες
Τα πρώτα χρόνια του PC υπήρχαν μόνο οι κάρτες οθόνης MDA (monochrome display
adapter) για μονόχρωμο κείμενο, CGA (color graphics adapter) και EGA (enhanced
graphics adapter) για κείμενο και γραφικά χαμηλής ανάλυσης. Από το
1991 και μετά έκαναν την εμφάνισή τους οι κάρτες VGA (video graphics array) με τις οποίες
μπορούμε να έχουμε πολύ καλές αναλύσεις και μεγάλο αριθμό χρωμάτων. Στον επόμενο
πίνακα φαίνονται οι βασικές κάρτες που χρησιμοποιούνται στο PC και
οι μέγιστες αναλύσεις τους.
Video Modes : Μπορούμε να έχουμε δύο τύπους οθόνης (video modes): κείμενο και
γραφικά. Όταν βρισκόμαστε σε text mode στην οθόνη μπορούν να εμφανιστούν μόνο οι
χαρακτήρες του πληκτρολογίου (και οι επεκταμένοι), οι οποίοι αντιστοιχούν σε όλα τα
ASCII σύμβολα. Τα χρώματα μπορεί να είναι ένα ή περισσότερα. Όταν βρισκόμαστε σε
graphics mode μπορούμε να απεικονίσουμε οποιοδήποτε σχήμα, ενεργοποιώντας
κατάλληλα τις στοιχειώδεις ψηφίδες (pixels) της οθόνης. Το μέγεθος των pixels αυτών είναι
τόσο μικρότερο, όσο μεγαλύτερη είναι η ανάλυση. Τα pixels μπορούν να έχουν ένα ή
περισσότερα χρώματα. Μερικά από τα πιο συνηθισμένα modes και οι κάρτες που τα
υποστηρίζουν φαίνονται στον επόμενο πίνακα.
Video Attributes: Όταν έχουμε οθόνη κειμένου, κάθε χαρακτήρας αντιστοιχεί σε δύο
bytes : ένα για τον κώδικα ASCII του χαρακτήρα και ένα για το attribute. Το attribute
είναι ένα byte που φανερώνει τον τρόπο εμφάνισης του χαρακτήρα, δηλαδή το χρώμα του,
αν θα είναι υπογραμμισμένος, έντονα φωτισμένος (highlight) ή αν αναβοσβήνει (blinks).
Για μονόχρωμη οθόνη κειμένου (video mode 7) τα διάφορα
attributes μπορεί να είναι τα εξής:
Τιμή Attribute
07H Κανονικό
28
Αν το MSB (bit 7) του attribute γίνει 1, τότε ο χαρακτήρας αναβοσβήνει. Για παράδειγμα,
το attribute 81H σημαίνει χαρακτήρας υπογραμμισμένος που αναβοσβήνει.
Σε έγχρωμο mode κειμένου (mode 3), το attribute δείχνει και το χρώμα του χαρακτήρα.
Εδώ δεν μπορούμε να έχουμε την επιλογή της υπογράμμισης, αλλά υπάρχει το
αναβόσβημα, η ανάστροφη εμφάνιση (reverse video) και η φωτεινότητα. Σε έναν
χαρακτήρα στην οθόνη ορίζονται δύο χρώματα: το foreground που είναι το χρώμα του
χαρακτήρα, και το background που είναι το χρώμα του υπόβαθρου, δηλαδή το χρώμα
της οθόνης πίσω από τον χαρακτήρα. Τα bits 0, 1 και 2 του attribute δείχνουν το
foreground color, ενώ τα bits 4, 5, και 6 δείχνουν το χρώμα του background. Το bit 3
δείχνει την φωτεινότητα του χρώματος foreground, δηλαδή αν είναι 1 τα χρώματα
γίνονται πιο ανοικτά. Έτσι στην ουσία είναι σαν να έχουμε 16 χρώματα για το
foreground. To bit 7 είναι το bit ενεργοποίησης του αναβοσβήματος. Στην κάρτα EGA
όμως το bit 7 έχει διπλή σημασία: Μπορεί να ρυθμίζει είτε το αναβόσβημα (blinking), είτε
την φωτεινότητα του background, επιτρέποντάς του έτσι να έχει και αυτό 16 χρώματα.
Η σημασία του bit 7 σε αυτή την περίπτωση καθορίζεται από την υποσυνάρτηση 03H
της συνάρτησης 10Η του ΙΝΤ 10Η (βλέπε και Παράρτημα Β). Οι κωδικοί των 16 αυτών
χρωμάτων φαίνονται στον ακόλουθο
πίνακα:
Στην συνέχεια θα δούμε ορισμένες από τις συναρτήσεις του ΙΝΤ 10Η του BIOS. Οι
ρουτίνες αυτές σώζουν τους segment registers και τους BX, CX, DX. Τους
υπόλοιπους πρέπει να τους σώζουμε εμείς αν χρειάζεται.
29
MOV AH, 0
MOV AL, 7
INT 21H
Μόλις εκτελεστούν οι παραπάνω εντολές, καθαρίζει ο οθόνη και βρισκόμαστε στο νέο
mode. Αν δεν θέλουμε να καθαρίσει η οθόνη, μπορούμε να θέσουμε 1 το ΜSB (bit 7)
του AL. Στο παράδειγμά μας θα έπρεπε να γράψουμε : MOV AL, 87H.
Ο δείκτης κειμένου (cursor) είναι ένα ορθογώνιο παραλληλόγραμμο με ύψος 1/25 της οθόνης
και πλάτος 1/80 του πλάτους της οθόνης (για οθόνη κειμένου 80Χ25), καταλαμβάνει δηλαδή
τον ίδιο χώρο με έναν χαρακτήρα. Το ορθογώνιο αυτό χωρίζεται σε 13 γραμμές για
μονόχρωμη οθόνη και 8 γραμμές για τις υπόλοιπες οθόνες. Η εμφάνιση του cursor εξαρτάται
από το πόσες από αυτές τις γραμμές είναι ενεργοποιημένες (φωτεινές). Το τυπικό είναι να
ενεργοποιούνται μόνο οι δύο τελευταίες γραμμές (βλέπε σχ. 4.1), οπότε ο cursor έχει την
γνωστή εμφάνιση της αναβοσβήνουσας παχιάς οριζόντιας γραμμής στο κάτω μέρος της
συγκεκριμένης
θέσης της οθόνης.
Με την συνάρτηση 01H του ΙΝΤ 10Η μπορούμε να καθορίσουμε το μέγεθος του κέρσορα.
Αρκεί να τοποθετήσουμε στον CH την αρχική και στον CL την τελική γραμμή. Για τυπικό
cursor σε μονόχρωμη οθόνη θα είναι CH=0BH και CL=0CH, ενώ για έγχρωμη οθόνη οι ίδιοι
καταχωρητές θα πρέπει να έχουν τιμές 06H και 07H αντίστοιχα.
Με την συνάρτηση αυτή τοποθετούμε τον cursor στην θέση που επιθυμούμε. Ο DL πρέπει
να περιέχει την στήλη (0-79), ο DH την γραμμή (0-24) και ο ΒΗ την τρέχουσα σελίδα της
οθόνης (συνήθως 0). Σε ένα video buffer μπορεί να είναι τοποθετημένες περισσότερες από
μία οθόνες (ή σελίδες όπως ονομάζονται), από τις οποίες όμως μόνο μία μπορεί να είναι
ενεργή, δηλαδή να εμφανίζεται. Το επόμενο παράδειγμα, θέτει mode 3 (έγχρωμο κείμενο),
μέγιστο μέγεθος κέρσορα και τοποθετεί τον κέρσορα στην μέση της οθόνης.
Η συνάρτηση αυτή μας επιστρέφει το μέγεθος και την θέση του cursor.
Συγκεκριμένα, η αρχική γραμμή του μεγέθους του cursor τοποθετείται στον CH, η τελική
γραμμή στον CL, η στήλη της θέσης στον DL και η γραμμή στον DH. Η συνάρτηση αυτή
είναι ιδιαίτερα χρήσιμη σε προγράμματα που χρησιμοποιούν μενού. Με την κλήση της και
ορισμένες συγκρίσεις, μπορούμε να αποφανθούμε ποιο μενού έχει επιλεγεί.
Με τις συναρτήσεις 06H (scroll window up) και 07H (scroll window down) μετακινούμε τα
31
δεδομένα ενός παραθύρου της οθόνης πάνω ή κάτω αντίστοιχα. Όταν για παράδειγμα ένα
παράθυρο μετακινείται προς τα πάνω (scrolls up) οι πάνω γραμμές χάνονται και στην
θέση των κάτω γραμμών που ανεβαίνουν, εισάγονται κενές γραμμές.
Σαν παράθυρο (window) ορίζεται μια ορθογώνια περιοχή της οθόνης, η οποία καθορίζεται
από τις συντεταγμένες του πάνω αριστερά και του κάτω δεξιά σημείου της. Με τον ορισμό
αυτό, ολόκληρη η οθόνη μπορεί να θεωρηθεί ένα παράθυρο με συντεταγμένες (0,0) και
(79, 24), όταν έχουμε κείμενο ανάλυσης 80Χ25. Στις συντεταγμένες οποιουδήποτε σημείου
της οθόνης πρώτα αναφέρουμε τις στήλες και μετά τις γραμμές.
Καταχωρητής Σημασία
AL Αριθμός γραμμών (0=όλες)
CH Γραμμή της πάνω αριστερά γωνίας του
παραθύρου
CL Στήλη της πάνω αριστερά γωνίας του παραθύρου
DH Γραμμή της κάτω δεξιά γωνίας του παραθύρου
DL Στήλη της κάτω δεξιά γωνίας του παραθύρου
BH Attribute των κενών γραμμών που θα εισαχθούν
Με την συνάρτηση αυτή διαβάζουμε τον χαρακτήρα που βρίσκεται στην τρέχουσα
θέση του cursor καθώς και το αντίστοιχο attribute. Συγκεκριμένα:
Παράμετροι εισόδου: AH
32
= 08H
BH = αριθμός σελίδας οθόνης
Παράμετροι εξόδου: AL
= χαρακτήρας ΑΗ =
attribute
Με την συνάρτηση αυτή μπορούμε να γράψουμε έναν χαρακτήρα και attribute σε μία ή
περισσότερες διαδοχικές θέσεις στην οθόνη. Συγκεκριμένα:
Παράμετροι εισόδου:
ΑΗ = 09H
AL = χαρακτήρας
ΒΗ = αριθμός σελίδας οθόνης
BL = attribute
CX = αριθμός επαναλήψεων
Έξοδος:
Ο χαρακτήρας και το attribute που δόθηκαν γράφονται από την τρέχουσα θέση του
cursor και κάτω, τόσες φορές όσες υποδεικνύει το περιεχόμενο του CX.
Με την συνάρτηση αυτή του ΙΝΤ 10Η μπορούν να γραφούν όλοι οι χαρακτήρες ASCII,
ακόμη και αυτοί με κωδικούς από 1 έως 31, οι οποίοι κανονικά χρησιμοποιούνται ως
χαρακτήρες ελέγχου. Εδώ όμως αυτοί οι κωδικοί παριστάνουν κάποια γραφικά σύμβολα, πχ
ο κωδικός 21 παριστάνεται σαν §.
Η συνάρτηση αυτή είναι ακριβώς ίδια με την 09H, με την διαφορά ότι εδώ δεν
αλλάζουμε το attribute.
Είσοδος:
ΑΗ = 0FH
Έξοδος:
ΑΗ = αριθμός στηλών της οθόνης
AL = video mode
BH = ενεργός σελίδα οθόνης
ΠΑΡΑΡΤΗΜΑ Α
1. Κατηγορίες Εντολών
Όλες οι εντολές της γλώσσας assembly του 8086 δίνονται στο Παράρτημα Α με αλφαβητική
σειρά και με συνοπτική επεξήγηση της λειτουργίας τους. Συνολικά αυτές μπορούν να
ομαδοποιηθούν σε 7 κατηγορίες, ανάλογα με τον σκοπό που εξυπηρετούν.
1. Μεταφοράς δεδομένων.
2. Αριθμητικές και λογικές.
3. Ολίσθησης και περιστροφής.
4. Χειρισμού αλφαριθμητικών (strings).
5. Χειρισμού των flags.
6. Ελέγχου προγράμματος.
7. Ελέγχου του μικροεπεξεργαστή.
Η ομάδα αυτή γενικά περιλαμβάνει εντολές που μεταφέρουν δεδομένα ανάμεσα στον
επεξεργαστή (καταχωρητές), την μνήμη και τις συσκευές εισόδου/εξόδου (Ι/Ο). Συνολικά
αυτές είναι οι : MOV, PUSH, POP, PUSHF, POPF, XCHG, XLAT, IN, OUT, LEA, LDS,
LES, CBW, CWD, LAHF και SAHF.
Με την εντολή MOV μπορούμε να μεταφέρουμε δεδομένα (bytes ή words) από καταχωρητή
σε καταχωρητή, από καταχωρητή σε θέση μνήμης και αντίστροφα, καθώς και να δώσουμε
άμεσα τιμές τόσο σε καταχωρητές όσο και σε θέσεις μνήμης. Όλα αυτά μπορούν να γίνουν
με πολλούς τρόπους, όσοι και οι τρόποι προσπέλασης της μνήμης και έτσι οδηγούμαστε σε
πάρα πολλούς συνδυασμούς της εντολής αυτής.
Εδώ πρέπει να αναφέρουμε ότι μια θέση μνήμης μπορεί να παρασταθεί με πολλούς
τρόπους (addressing modes). Αυτοί είναι :
• Άμεσος : Δίνεται η ίδια η διεύθυνση ή ένα label το οποίο έχει αντιστοιχηθεί στην
διεύθυνση αυτή. Π.χ. [00Α0Η] ή list1. Η διεύθυνση αυτή είναι το offset. Segment
θεωρείται πάντα ο DS, εκτός αν αναφέρεται άλλος segment register.
• Έμμεσος : Η διεύθυνση της θέσης (offset) βρίσκεται στο περιεχόμενο ενός
καταχωρητή. Για τον σκοπό αυτό μπορούν να χρησιμοποιηθούν μόνο οι καταχωρητές
βάσης ΒΧ και ΒΡ, καθώς και οι δείκτες SI, DI.
• Βάση συν δείκτης : Το offset της διεύθυνσης βρίσκεται αν προσθέσουμε τα
περιεχόμενα των εν λόγω καταχωρητών (στο άθροισμα κρατάμε τα 16
χαμηλότερα bit). Π.χ. [ΒΧ+SI], [BP+DI].
• Βάση (ή δείκτης) συν μετατόπιση : π.χ. [ΒΧ+5] ή array[BX]. Στην πρώτη
περίπτωση η διεύθυνση που προκύπτει έχει offset το περιεχόμενο του ΒΧ συν 5, ενώ στο
δεύτερο παράδειγμα υπολογίζεται το offset του array και σε αυτό προστίθεται το
περιεχόμενο του ΒΧ.
• Βάση συν δείκτης συν μετατόπιση : π.χ. [ΒΡ+SI+4] ή table[ΒΧ+DI].
Παραδείγματα :
Η εντολή PUSH αντιγράφει μια λέξη στον σωρό και μειώνει τον SP κατά 2, ενώ η εντολή
ΡΟΡ αντιγράφει την λέξη που βρίσκεται στην κορυφή του σωρού στην παράμετρο που την
ακολουθεί.
Παραδείγματα :
PUSH AX Αντιγράφει το περιεχόμενο του ΑΧ στον σωρό.
ΡΟΡ ΒΧ Αντιγράφει στον ΒΧ την λέξη που βρίσκεται στην κορυφή του
σωρού.
PUSH ABCDH Αντιγράφει τον αριθμό ΑΒCDH στην κορυφή του σωρού.
PUSH WORD PTR [BX] Αντιγράφει στον σωρό την λέξη που βρίσκεται στην
διεύθυνση DS:BX. Tο directive WORD PTR δηλώνει ότι
στην αντίστοιχη διεύθυνση βρίσκεται word και όχι byte. (βλ.
αντίστοιχο κεφάλαιο για τα directives).
PUSH ‘A’ Αντιγράφει τον ASCII χαρακτήρα ‘Α’ σαν δύο byte
στον σωρό, δηλ. αντιγράφει το 0041H.
PUSHF Αντιγράφει τον flag register στον σωρό.
POPF Αντιγράφει την κορυφή του σωρού στον flag register. POP
CS Δεν επιτρέπεται να γράφουμε τίποτα στον CS.
Η εντολή LEA υπολογίζει και φορτώνει το offset ενός τελεστή μνήμης σε έναν
37
καταχωρητή.
Παράδειγμα :
Η εντολή αυτή είναι ίδια με την MOV AX, OFFSET NAME1, όπου το directive OFFSET
επιβάλει στον επεξεργαστή να υπολογίσει το offset του τελεστή ΝΑΜΕ1 (βλ. αντίστοιχο
κεφάλαιο για τα directives του assembler).
Η εντολή LDS αντιγράφει 4 bytes από μια θέση μνήμης που δίνεται σαν παράμετρος σε
κάποιον καταχωρητή (που επίσης δίνεται σαν παράμετρος) και στον DS. H LES κάνει την
ίδια δουλειά αλλά χρησιμοποιεί τον ES (βλ. και παράρτημα Α).
Παράδειγμα :
Οι εντολές ΙΝ και OUT χρησιμεύουν για την μεταφορά δεδομένων μεταξύ του επεξεργαστή
και των συσκευών εισόδου / εξόδου (Ι/Ο). Για τον σκοπό αυτό χρησιμοποιούνται οι
καταχωρητές AL ή ΑΧ για την μεταφορά byte ή λέξεων αντίστοιχα. Η διεύθυνση της θύρας
(port) εισόδου/εξόδου μπορεί να δοθεί είτε άμεσα σαν 8μπιτος αριθμός, είτε έμμεσα σαν
16μπιτος αριθμός μέσω του DX. Αυτό φαίνεται καλύτερα στα παραδείγματα που
ακολουθούν.
Παραδείγματα :
IN AL, 42H 8 bits εισάγονται στον AL από την θύρα 42H. OUT
6BH, AX Το περιεχόμενο του ΑΧ εξάγεται στην θύρα 6ΒΗ.
ΙΝ ΑX, DX 16 bits εισάγονται στον AX από την θύρα που δείχνει ο DX. OUT
DX, AL Το περιεχόμενο του ΑL εξάγεται στην θύρα που δείχνει ο DX.
Στον 8086 οι διευθύνσεις των θυρών είναι 16μπιτοι αριθμοί, καταλαμβάνουν δηλαδή τις 16
κατώτερες θέσεις του address bus (A0-A15). To περιεχόμενο των ακροδεκτών Α16-Α19 είναι
αδιάφορο. Όταν η διεύθυνση μιας θύρας δίνεται σαν 8μπιτος αριθμός, αυτός επεκτείνεται σε
16μπιτο θέτοντας 0 τα 8 υψηλότερης τάξης bit. Αυτά φαίνονται καλύτερα στο σχήμα 1 που
38
περιγράφει το περιεχόμενο των ακροδεκτών που επηρεάζονται κατά την εκτέλεση της
εντολής OUT 25H, AX.
Σχ. 1 Τα σήματα που παράγονται κατά την εκτέλεση της εντολής OUT 25H, AX.
Να σημειώσουμε εδώ ότι η INTEL φυλάσσει τις τελευταίες 16 διευθύνσεις θυρών Ι/Ο
για τα διάφορα περιφερειακά του PC.
Από τις υπόλοιπες εντολές μεταφοράς δεδομένων, οι LAHF και SAHF χρησιμοποιούνται
πολύ σπάνια πλέον (χρησίμευαν για μετάφραση προγραμμάτων του παλιότερου 8085). Η
εντολή XCHG ανταλλάσσει ένα byte ή μια λέξη ανάμεσα στην παράμετρο πηγής και στην
παράμετρο προορισμού π.χ. η XCHG AX, BX θα ανταλλάξει τα περιεχόμενα των ΑΧ και
ΒΧ.
Τέλος η XLAT είναι μια δυνατή εντολή που μετατρέπει το περιεχόμενο του AL σε μια
τιμή που βρίσκει σε έναν πίνακα δεδομένων της μνήμης. Συγκεκριμένα προσθέτει στον ΒΧ
τον AL (η μοναδική εντολή που προσθέτει έναν 8μπιτο με έναν 16μπιτο αριθμό) και το
άθροισμα αυτό θα είναι η απόκλιση (offset) μιας θέσης μνήμης στο data segment. Το
περιεχόμενο της θέσης αυτής θα αντιγραφεί στον AL. Η εντολή αυτή είναι χρήσιμη για
μετατροπή από έναν κώδικα σε άλλον, για παράδειγμα από BCD σε 7-segment κώδικα για
αναπαράσταση σε οθόνες LCD.
39
Στην συνέχεια θα δώσουμε ένα μικρό πρόγραμμα που κάνει την μετατροπή του περιεχομένου
του AL (αν υποθέσουμε ότι είναι ένας αριθμός από το 0 έως το 9) σε κώδικα 7-segment με
χρήση της XLAT. Την δομή του προγράμματος θα την καταλάβετε πλήρως αφού διαβάσετε
και το επόμενο κεφάλαιο. Σημασία έχει εδώ να δούμε πώς αντιστοιχίζεται το περιεχόμενο
του ΑL στην αναπαράστασή του σε 7- segment.
.MODEL SMALL
.DATA
.CODE
DOS_EXIT:
MOV AH,4CH MOV
AL,0
INT 21H END
40
Τέλος η CBW (μετατροπή byte σε λέξη) αντιγράφει το bit προσήμου του AL σε όλα τα bits
του ΑΗ, ενώ η CWD (μετατροπή word σε doubleword) αντιγράφει το bit προσήμου του ΑΧ
σε όλα τα bit του DX.
Οι αριθμητικές πράξεις που εκτελεί η CPU είναι πρόσθεση, αφαίρεση, πολλαπλασιασμός και
διαίρεση ακεραίων (προσημασμένων ή μη). Αναλυτικά σε κάθε πράξη ανήκουν οι εξής
εντολές :
Πρόσθεση :
ADD, ADC, INC, AAA, DAA
Αφαίρεση :
SUB, SBB, DEC, NEG, CMP, AAS, DAS
Πολλαπλασιασμός :
MUL, IMUL, AAM
Διαίρεση :
DIV, IDIV, AAD
Οι εντολές αυτές περιγράφονται αναλυτικά στο Παράρτημα Α και είναι μάλλον περιττή
περαιτέρω εξήγηση. Τα ακόλουθα εξάλλου παραδείγματα διευκρινίζουν την λειτουργία
των σημαντικότερων από αυτές.
Παραδείγματα :
Οι εντολές αυτές εκτελούν τις αντίστοιχες λογικές πράξεις σε κάθε ένα από τα bit της
παραμέτρου (βλ. Παράρτημα Α).
Παραδείγματα :
Εδώ πρέπει να σημειώσουμε ότι τόσο οι αριθμητικές όσο και οι λογικές εντολές δεν μπορούν
να δράσουν πάνω σε segment registers, καθώς και ότι δεν μπορούν επίσης και οι δυο
παράμετροι να είναι τελεστές μνήμης.
Οι εντολές ολίσθησης και περιστροφής (shift and rotate) διαχειρίζονται δυαδικούς αριθμούς
σε επίπεδο bit όπως και οι λογικές εντολές. Χρησιμοποιούνται συνήθως σε low-level
software για έλεγχο των συσκευών Ι/Ο. Παρέχεται πλήρες σετ που μπορεί να ολισθήσει ή
να περιστρέψει δεξιά ή αριστερά το περιεχόμενο οποιουδήποτε καταχωρητή ή θέσης μνήμης
(εκτός των segment registers).
Ολισθήσεις :
SHL, SAL, SHR, SAR
Περιστροφές :
ROL, ROR, RCL, RCR
Όπως παρατηρούμε, υπάρχουν δύο δεξιές και δύο αριστερές ολισθήσεις. Οι λογικές
ολισθήσεις (SHL, SHR) χρησιμοποιούνται με μη προσημασμένους αριθμούς, ενώ οι
αριθμητικές ολισθήσεις (SAL, SAR), χρησιμοποιούνται με προσημασμένους αριθμούς. Η
λειτουργία τους φαίνεται στο σχ. 3. Οι εντολές SHL και SAL έχουν ακριβώς την ίδια
λειτουργία.
43
Τόσο οι εντολές ολίσθησης όσο και οι εντολές περιστροφής μπορούν να επαναληφθούν τόσες
φορές όσο το περιεχόμενο του μετρητή CL. Το περιεχόμενο του CL είναι εκφρασμένο σε
modulo 32, δηλαδή ο αριθμός που περιέχει ο CL διαιρείται με το 32 και το υπόλοιπο της
44
Παράδειγμα :
MOV CL, 34
SHL BH, CL
Στον 8086 υπάρχει ένα πολύ δυνατό σετ εντολών χειρισμού αλφαριθμητικών (strings) με τις
οποίες μπορούμε να χειριστούμε με ευκολία μεγάλα μπλοκ δεδομένων. Οι εντολές αυτές
μπορούν να χωριστούν σε τρεις υποομάδες, τις εντολές μεταφοράς μπλοκ δεδομένων LODS,
STOS και MOVS, τις εντολές εύρεσης CMPS και SCAS και τις εντολές επανάληψης REP,
REPE/REPZ και RENE/REPNZ.
Παραδείγματα :
LODSW AXÅDS:[SI] , SIÅSI±2
LODS DATA1 ALÅDS:[SI], SIÅSI±1 αν DATA1 είναι byte ή
AXÅDS:[SI], SIÅSI±2 αν DATA1 είναι word.
STOSB ES:[DI]ÅAL, DIÅDI±1
MOVSW ES:[DI]ÅDS:[SI], DIÅDI±2, SIÅSI±2 (μεταφορά λέξης). REP
MOVSB Η εντολή MOVSB εκτελείται τόσες φορές όσο το περιεχόμενο
του CX, o CX καθορίζει δηλαδή το μέγεθος του μπλοκ μνήμης που
θα μεταφερθεί από το data στο extra segment.
Έστω ότι θέλουμε να μεταφέρουμε το μπλοκ μνήμης από 0500:0100 έως 0500:0300 στις
θέσεις μνήμης Α000:0000 έως Α000:0200. Το μήκος του μπλοκ είναι 200Η bytes. Το
παρακάτω τμήμα προγράμματος κάνει αυτή την εργασία.
CLD
REP MOVSB
Η εντολή SCAS (scan string) συγκρίνει το byte (SCASB) ή το word (SCASW) που βρίσκεται
στην διεύθυνση ES:DI με τον AL ή τον ΑΧ αντίστοιχα. Η σύγκριση επηρεάζει μόνο τα flags.
Σε συνδυασμό με την REPNE (ή την όμοια REPNZ) μπορεί να χρησιμοποιηθεί για να βρει
ένα byte ή μια λέξη κλειδί σε ένα μπλοκ μνήμης. Το επόμενο πρόγραμμα ψάχνει στο μπλοκ
που αρχίζει από την διεύθυνση 0100:0Α00 και έχει μήκος 1 Kbyte για να βρει το byte BBH.
Η εντολή αυτή μπορεί επίσης να χρησιμοποιηθεί με την REPE (ή την όμοια REPZ), σε
ρουτίνες παράκαμψης επαναλαμβανόμενου byte ή word. Το κομμάτι προγράμματος που
ακολουθεί παρακάμπτει (πηδά) τον χαρακτήρα ΄΄κενό΄΄ (ASCII
20H) σε κάποιο string που ξεκινά από την διεύθυνση ES:DI.
CLD
MOV CX, 0FFFFH MOV
AL, 20H REPE SCASB
ES, AX
MOV AX, 0BOOOH MOV
DS, AX
MOV DI, 100H
MOV SI, 3E00H CLD
MOV CX, 100
REPE CMPSB
Αν τα δυο μπλοκ είναι ίδια, στο τέλος του προγράμματος ο CX θα έχει μηδενιστεί και το zero
flag θα είναι 1. Σε αντίθετη περίπτωση, δηλ. αν είτε CX>0 είτε Ζ=0, τα δυο μπλοκ δεν θα
έχουν ακριβώς το ίδιο περιεχόμενο.
Οι εντολές αυτές είναι οι CLC, STC, CLD, STD, CLI, STI και CMC. Η λειτουργία τους
έχει ως εξής :
Με χρήση της εντολής JMP (jump) μπορούμε να μεταβούμε σε όποιο σημείο του
προγράμματος θέλουμε. Η εντολή αυτή υπάρχει σε τρεις εκδοχές : short jump, near jump και
far jump.
Tα short jumps επιτρέπουν διακλαδώσεις από –128 έως +127 θέσεις μνήμης από την θέση
της επόμενης εντολής που πρόκειται να εκτελεστεί. Η αντίστοιχη εντολή έχει μέγεθος 2
bytes, ένα για τον λειτουργικό κώδικα της εντολής (opcode) και ένα για την τιμή της
μετατόπισης (displacement) που είναι προσημασμένος 8μπιτος αριθμός. Ο αριθμός αυτός
προστίθεται στην τιμή του ΙΡ, έτσι ώστε να προκύψει η διεύθυνση διακλάδωσης.
Τα near jumps επιτρέπουν διακλαδώσεις μέχρι ±32Κ θέσεις μνήμης από την διεύθυνση της
επόμενης προς εκτέλεση εντολής. Έτσι μπορούν να προσπελάσουν οποιαδήποτε διεύθυνση
στο τρέχον segment (μεγέθους 64Κ). Αυτό συμβαίνει επειδή
49
τα segments είναι κυκλικά, δηλαδή αν η επόμενη προς εκτέλεση εντολή είναι στην θέση
με offset 0004H και εμείς θέλουμε να μεταβούμε στην θέση FFFFH, αρκεί να δώσουμε
ως displacement το –5. Το near jump έχει μέγεθος 3 bytes, ένα για τον opcode και δύο
για το displacement. To displacement είναι προσημασμένος 16μπιτος αριθμός που
προστίθεται στον ΙΡ για να προκύψει η διεύθυνση διακλάδωσης.
Τόσο τα short όσο και τα near jumps ονομάζονται και σχετικά (relatives), διότι τα
προγράμματα που τα χρησιμοποιούν μπορούν να επανατοποθετηθούν σε άλλο σημείο της
μνήμης χωρίς αλλαγές στον κώδικα. Αυτό συμβαίνει διότι δεν δίνουμε άμεσα τιμή
στον ΙΡ, αλλά μετατόπιση από την τρέχουσα τιμή του, όποια και αν είναι αυτή.
Εκτός της εντολής JMP που είναι εντολή διακλάδωσης χωρίς συνθήκη, υπάρχουν και οι
εντολές διακλάδωσης υπό συνθήκη που προαναφέρθηκαν. Αυτές όμως κάνουν μόνo
short jumps (-128 έως +127 θέσεις).
Παράδειγμα :
Το επόμενο πρόγραμμα βρίσκει τον μικρότερο από τρεις αριθμούς και τον τοποθετεί στον
DL. Οι τρεις αριθμοί βρίσκονται αρχικά στους AL, BL, CL.
50
Τέλος υπάρχει η δυνατότητα για indirect jumps, δηλαδή για χρήση καταχωρητών ή τελεστών
μνήμης για την εύρεση της διεύθυνσης μετάβασης. Το περιεχόμενο του καταχωρητή ή της
θέσης μνήμης θα τοποθετηθεί στον ΙΡ. Θεωρούμε πάντα ότι έχουμε near jumps, εκτός
αν βάλουμε το directive FAR PTR.
Παραδείγματα :
JMP FAR PTR [SI] Ο ΙΡ θα πάρει ως νέα τιμή το περιεχόμενο των διευθύνσεων DS:[SI],
DS:[SI+1] και ο CS το DS:[SI+2], DS:[SI+3]. Έτσι θα προκύψει μια
νέα διεύθυνση σε άλλο segment (far address).
Η εντολή LOOP (επανάληψη χωρίς συνθήκη) είναι ένας συνδυασμός των εντολών DEC CX
και JNZ, δηλαδή μειώνει την τιμή του CX (μετρητής επαναλήψεων) κατά 1, και αν αυτός δεν
έχει γίνει 0, μεταπηδά στην διεύθυνση που δίνεται σαν παράμετρος. Η διεύθυνση βέβαια αυτή
δεν μπορεί να είναι μακρύτερα από –128 έως +127 θέσεις από την θέση της επόμενης προς
εκτέλεση εντολής.
Εκτός της LOOP υπάρχουν και οι εντολές επανάληψης υπό συνθήκη που προαναφέρθηκαν.
Παράδειγμα :
Το επόμενο πρόγραμμα ψάχνει μέσα σε μια σειρά δεδομένων (ARRAY1) μήκους 100
λέξεων μέχρι να βρει την πρώτη μη μηδενική λέξη. Η εντολή CMP WORD PTR [AX],
0 συγκρίνει το περιεχόμενο κάθε λέξης με το 0, και όσο αυτά είναι ίσα το Ζ=1,
άρα ο βρόγχος επαναλαμβάνεται.
Οι υπορουτίνες (procedures ή subroutines) είναι ένα σύνολο εντολών που εκτελούν κάποια
συγκεκριμένη εργασία. Ενώ γράφονται μόνο μια φορά, μπορούν να προσπελαστούν πολλές
φορές στην διάρκεια εκτέλεσης ενός προγράμματος. Η ύπαρξη υπορουτινών, πέρα από
την προφανή μείωση του όγκου ενός προγράμματος, δίνει την δυνατότητα δημιουργίας
βιβλιοθηκών που θα χρησιμοποιούνται από όλα τα προγράμματα του χρήστη. Το μόνο
μειονέκτημα είναι ο χρόνος μετάβασης και επιστροφής στο κυρίως πρόγραμμα.
Κάθε υπορουτίνα (procedure) έχει ένα όνομα με το οποίο καλείται από την εντολή CALL
52
και τελειώνει πάντα με την εντολή RET, η οποία επιστρέφει τον έλεγχο στην επόμενη εντολή
από την κλήση της υπορουτίνας.
AX, AX
ADC AX, BX RET
EQU1 ENDP
Η εντολή CALL όπως προαναφέρθηκε, κάνει ένα άλμα στην διεύθυνση της υπορουτίνας το
όνομα της οποίας δίνεται σαν παράμετρος. Πριν όμως από αυτό, και αυτή είναι η διαφορά
της με την εντολή JMP, σώζει στον σωρό την διεύθυνση της επόμενης προς εκτέλεση
εντολής, έτσι ώστε να μπορέσει αργότερα να επιστρέψει στο σωστό σημείο του κυρίως
προγράμματος.
Η εντολή CALL μπορεί να είναι near (κλήση υπορουτίνας που βρίσκεται στο ίδιο
segment), οπότε σώζεται στον σωρό μόνο ο ΙΡ, ή far (κλήση υπορουτίνας που βρίσκεται σε
άλλο segment), οπότε σώζονται τόσο ο ΙΡ όσο και ο CS. Επίσης, όμοια με την εντολή JMP,
μπορούμε να χρησιμοποιήσουμε σαν παράμετρο κάποιον καταχωρητή ή τελεστή μνήμης, το
περιεχόμενο των οποίων θα μας δίνει την διεύθυνση της υπορουτίνας που θέλουμε να
καλέσουμε.
Η εντολή RET αν βρίσκεται μέσα σε υπορουτίνα που έχει δηλωθεί σαν near επαναφέρει από
τον σωρό το περιεχόμενο του ΙΡ, ενώ αν η υπορουτίνα έχει δηλωθεί σαν far, επαναφέρονται
τόσο ο ΙΡ όσο και ο CS.
Οι εντολές ΙΝΤ, ΙΝΤΟ και IRET περιγράφονται στο κεφάλαιο για τις διακοπές. Εδώ θα
παρατηρήσουμε μόνο ότι η εντολή ΙΝΤ είναι παρόμοια με μια εντολή far CALL στην
διεύθυνση της ρουτίνας εξυπηρέτησης της διακοπής. Τα πλεονεκτήματα όμως της χρήσης
53
1. Η ΙΝΤ έχει σαν παράμετρο μόνο έναν 8μπιτο αριθμό (τον τύπο της διακοπής) ενώ η far
CALL έχει σαν παράμετρο 4 byte (segment και offset της διεύθυνσης της υπορουτίνας).
Έτσι, η εντολή ΙΝΤ έχει μέγεθος μόνο δύο byte ενώ η far CALL έχει μέγεθος 5 byte,
κάτι που σημαίνει ότι κερδίζουμε σημαντικά σε μέγεθος και ταχύτητα προγράμματος, αν
λάβουμε μάλιστα υπ΄όψη την συχνότητα χρήσης της ΙΝΤ.
2. Η εντολή ΙΝΤ σώζει αυτόματα και τον flag register (F), κάτι που διαφορετικά θα έπρεπε
να γίνεται σε όλες τις ρουτίνες εξυπηρέτησης διακοπών.
3. Επιτρέπεται η λειτουργία των προγραμμάτων ανεξάρτητα συστήματος. Ο
προγραμματιστής δηλαδή δεν χρειάζεται να γνωρίζει τις διευθύνσεις στην μνήμη των
ρουτινών του συστήματος, κάτι άλλωστε που αλλάζει από κατασκευαστή σε
κατασκευαστή. Αυτό είναι και το σημαντικότερο πλεονέκτημα, διότι έτσι ένα πρόγραμμα
assembly μπορεί να εκτελείται σε όλα τα PC.
ΠΑΡΑΡΤΗΜΑ Β
Λειτουργίες
1. new: Δημιουργία ενός νέου αρχείου προγράμματος
2. code examples: Παραδείγματα εκμάθησης συμβολικής γλώσσας του 8086. Τα
παραδείγματα καλύπτουν ευρύ φάσμα λειτουργιών από απλές έως πολύ σύνθετες
3. quick start tutor: οδηγίες χρήσης του περιβάλλοντος emu8086 (και της συμβολικής γλώσσας
8086)
4. recent files: Λίστα με τα πιο πρόσφατα αρχεία
55
Λειτουργίες
1. COM template: Δημιουργία εκτελέσιμου αρχείου .com
2. EXE template: Δημιουργία εκτελέσιμου αρχείου .exe
3. BIN template: δημιουργία δυαδικού εκτελέσιμου αρχείου για ενσωμάτωση σε μια μνήμη (π.χ.
ROM για απευθείας εκτέλεση από ένα σύστημα χωρίς τη μεσολάβηση λειτουργικού
συστήματος.
4. ΒΟΟΤ template: Αρχείο προγράμματος εκκίνησης ενός συστήματος (δεν απαιτείται η ύπαρξη
λειτουργικού συστήματος)
5. empty workspace: Κενό πρότυπο. Όλα τα τμήματα προγράμματος ορίζονται από τον
προγραμματιστή
6. the emulator: Απευθείας εκτέλεση του εξομοιωτή
56
Λειτουργίες
1. new: Δημιουργία νέου αρχείου προγράμματος (Οδηγεί στον προηγούμενο κατάλογο
επιλογών)
2. open: Άνοιγμα έτοιμου αρχείου προγράμματος
3. save: Αποθήκευση του αρχείου που είναι ανοιχτό στο περιβάλλον ανάπτυξης
4. compile: Έλεγχος σφαλμάτων, συμβολομετάφραση και δημιουργία του αρχείου
προγράμματος όπως περιγράφεται από το πρότυπο που έχουμε διαλέξει (.EXE,.COM,.BIN)
5. emulate: Έλεγχος σφαλμάτων και συμβολομετάφραση για την εκτέλεση του προγράμματος
στον εξομοιωτή
6. calculator: πρόγραμμα εκτέλεσης πράξεων μεταξύ τελεστέων στα 4 βασικά συστήματα
αρίθμησης (Δεκαδικό , Δεκαεξαδικό, Δυαδικό, Οκταδικό)
7. convertor: πρόγραμμα μετατροπής αριθμών μεταξύ των τεσσάρων βασικών συστημάτων
αρίθμησης (Δεκαδικό , Δεκαεξαδικό, Δυαδικό, Οκταδικό)
8. options: Ρυθμίσεις περιβάλλοντος του emu8086
9. help: Οδηγίες χρήσης του emu8086, οδηγίες ανάπτυξης προγραμμάτων στην αρχιτεκτονική
του 8086, κατάλογος εντολών 8086 και διακοπών του 8086.
57
Στην παραπάνω περίπτωση η λάθος συμβολομετάφραση οφείλεται στην εντολή με αριθμό 19 του
κώδικα (MOV si,al) όπου εσφαλμένα ένας καταχωρητής 16 bit λαμβάνει την τιμή ενός καταχωρητή 8
bit.
58
1 2 3
Λειτουργίες
Η οθόνη του εξομοιωτή περιέχει τρία βασικά παράθυρα. Το πρώτο παράθυρο περιέχει τις τιμές των
καταχωρητών του 8086 όπως αυτές ενημερώνονται μετά την εκτέλεση κάθε εντολής. Το δεύτερο
παράθυρο περιέχει τις φυσικές διευθύνσεις στη μνήμη και την τιμή που περιέχεται σε κάθε μια από
αυτές (σε δεκαεξαδική και σε δεκαδική τιμή). Οι τιμές που αντιστοιχούν στην επόμενη προς
εκτέλεση εντολή έχουν μπλέ υπόβαθρο. Η αρχή της επόμενης προς εκτέλεση εντολής υπολογίζεται
από το ζευγάρι καταχωρητών CS:IP. Στο τρίτο παράθυρο απεικονίζονται οι εντολές του αρχείου
προγράμματος όπου έχουν αντικατασταθεί οι ετικέτες κάθε είδους με τις τιμές που αντιστοιχούν σε
αυτές, όπως υπολογίστηκαν κατά τη συμβολομετάφραση, ενώ έχουν αντικατασταθεί και όλες οι
μακροεντολές με τον κώδικα που αντιστοιχεί σε αυτές. Η επόμενη προς εκτέλεση εντολή σε αυτό το
παράθυρο έχει επίσης μπλε υπόβαθρο.
1. Load: φωρτώνει ένα αρχείο (.asm,.com,.exe) ώστε να εξομοιώσει τη λειτουργία των εντολών
που περιέχονται
2. reload: Επαναρχικοποιούν τους καταχαρητές στις τιμές που είχαν πριν την εκτέλεση
(εξομοίωση) ενός προγράμματος.
3. step back: αναίρεση της εκτέλεσης της τελευταίας εντολής.
4. single step: Εκτελεί την επόμενη προς εκτέλεση εντολή
5. run: εκτελεί το πρόγραμμα που έχει φορτωθεί στον εξομοιωτή είτε ολόκληρο είτε μέχρι το
σημείο ενός Breakpoint εφόσον έχει οριστεί.
59
6. Κλίμακα step delay: Ορίζει το χρόνο μεταξύ της εκτέλεσης διαδοχικών εντολών.
Εκτός από την κεντρική οθόνη του εξομοιωτή αναπτύσσεται και η οθόνη του παρακάτω σχήματος
η οποία περιέχει το αρχικό αρχείο προγράμματος όπου είναι επισημασμένη η επόμενη προς
εκτέλεση εντολή σε συμφωνία με τη σήμανση στο κεντρικό παράθυρο του εξομοιωτή
Η επιλογή stack στο κάτω μέρος του κεντρικού παραθύρου του εξομοιωτή (ή view→stack) οδηγεί
την παρακάτω οθόνη,
60
Στο παράθυρο αυτό επισημαίνεται η θέση στην οποία βρίσκεται η κορυφή του σωρού με το <.
Η επιλογή debug (view→log and debug.exe emulation) στο κάτω μέρος του κεντρικού παραθύρου
του εξομοιωτή επιστρέφει τις τιμές των καταχωρητών το διάνυσμα κατάστασης του επεξεργαστή
όπως και τις λεπτομέρειες τις επόμενης προς εκτέλεσης εντολής. Ένα χαρακτηριστικό παράδειγμα
απεικονίζεται στο ακόλουθο σχήμα
Η επιλογή vars στο κάτω μέρος του κεντρικού παραθύρου του εξομοιωτή ( ή view→vars) αναπτύσσει
την οθόνη που απεικονίζει το παρακάτω σχήμα
Στην οθόνη αυτή περιέχονται οι μεταβλητές που είναι ορισμένες στο πρόγραμμα το μέγεθος που
καταλαμβάνει κάθε τιμή αυτής (byte,word) καθώς και το πόσα στοιχεία έχει η κάθε μεταβλητή και
το αριθμητικό σύστημα που επιθυμούμε να απεικονιστεί.
Με την επιλογή aux→memory (view→memory) μπορεί να απεικονιστεί ένα τμήμα 128 byte της
μνήμης όπως φαίνεται στο ακόλουθο σχήμα για το οποίο μπορούμε να ορίσουμε τη διεύθυνση
61
αρχής αλλά και να γράψουμε απευθείας νέες τιμές στις διάφορες θέσεις. Η αλλαγή περιεχομένων
της μνήμης μπορεί να γίνει είτε αλλάζοντας τη δεκαεξαδική αναπαράσταση είτε την ASCII.
62
ΠΑΡΑΡΤΗΜΑ Γ
Στην συνέχεια παραθέτονται αναλυτικά όλες οι εντολές του 8086, με την σύνταξη της
καθεμιάς, σύντομη εξήγηση λειτουργίας και επίδρασή της επί των διαφόρων flags. Επίσης
αναφέρονται οι χρόνοι εκτέλεσης της κάθε εντολής σε περιόδους ρολογιού (Τ).
Στους χρόνους αυτούς προστίθεται ορισμένες φορές το ea (Effective Address), που είναι
ο χρόνος υπολογισμού της φυσικής διεύθυνσης ενός τελεστή μνήμης. Οι χρόνοι αυτοί
διαφέρουν ανάλογα με τον τύπο του τελεστή μνήμης και φαίνονται αναλυτικά στον Πίνακα
Α.1. Αυτοί οι χρόνοι αφορούν υπολογισμούς για το εξ ορισμού segment. Όταν
καθορίζουμε διαφορετικό segment από το εξ ορισμού (segment override), για παράδειγμα
στην εντολή MOV DL, ES:[AX], πρέπει σε αυτούς τους χρόνους να
προσθέσουμε άλλα 2Τ.
Αν το κουτάκι ενός flag είναι κενό, σημαίνει ότι η εντολή δεν επιδρά στο αντίστοιχο
flag.
Για την σύντομη παρουσίαση της σύνταξης της κάθε εντολής, χρησιμοποιούμε τον
εξής συμβολισμό: ΕΝΤΟΛΗ dest, source, όπου το όνομα της εντολής μπορεί να
63
reg Ένας εκ των καταχωρητών: AX, BX, CX, DX, AH, AL, BH, BL, CH,
CL, DH, DL, SI, DI, BP ή SP.
seg Ένας καταχωρητής segment (CS, DS, SS, ES). acc
Συσσωρευτής (ΑΧ ή AL).
mem Ένας τελεστής μνήμης (πχ. day1, ES:[DI], [1234], [ΒΧ + 0ΑΗ] κτλ.
shortlabel Μια τοποθεσία –128 έως +127 bytes από την επόμενη εντολή. nearlabel
Μια τοποθεσία μέσα στο ίδιο segment.
farlabel Μια τοποθεσία σε διαφορετικό segment. imm
Μια άμεσα διδόμενη τιμή (πχ. 29).
I T S Z A P C
? ? ? * ? *
Διορθώνει το αποτέλεσμα στον AL , μετά την πρόσθεση δύο ASCII ψηφίων. Οι δεκαδικοί
αριθμοί (0-9) στον ASCII κώδικα καταλαμβάνουν τους κωδικούς από 30Η έως 39H,
επομένως μια απευθείας πρόσθεση οδηγεί σε λάθος αποτέλεσμα.
D I T S Z A P C
? * * ? * ?
D I T S Z A P C
? * * ? * ?
O D I T S Z A P C
? ? ? * ? *
O D I T S Z A P C
* * * * * *
Σύνταξη:
ADC reg, reg (3Τ) ADC reg, mem (9Τ+ea) ADC
reg, imm (4Τ) ADC mem, reg (16+ea) ADC mem,
imm (17+ea)
Παραδείγματα:
ADD Addition
O D I T S Z A P C
* * * * * *
Πρόσθεση της παραμέτρου πηγής στην παράμετρο προορισμού και αποθήκευση του
αθροίσματος στην παράμετρο προορισμού.
Σύνταξη:
ADD reg, reg (3T) ADD reg, mem (9T+ea)
65
O D I T S Z A P C
* * * ? * 0
Όλα τα bit της παραμέτρου προορισμού γίνονται λογικό ΚΑΙ με τα αντίστοιχα bit της
παραμέτρου πηγής και το αποτέλεσμα αποθηκεύεται στην παράμετρο προορισμού
Σύνταξη:
AND reg, reg (3T) AND reg, mem (9T+ea) AND
reg, imm (4T) AND mem, reg (16T+ea) AND
mem, imm (17T+ea)
Παραδείγματα: AND
AX, CX
AND data1, BL AND
AH, date[DI]
O D I T S Z A P C
Σύνταξη:
CALL nearlabel (19T) CALL mem (21T+ea)
CALL farlabel (28T) CALL reg (16T)
Παραδείγματα:
CALL clear_screen
CALL AX CALL
ES:[DI]
O D I T S Z A P C
Σύνταξη:
CBW
Αν το bit προσήμου (MSB) του AL είναι 1 ο AH γίνεται ίσος με FFH αλλιώς γίνεται ίσος
με 00Η (επέκταση προσήμου).
O D I T S Z A P C
0
O D I T S Z A P C
0
O D I T S Z A P C
0
67
O D I T S Z A P C
*
CMP Compare
O D I T S Z A P C
* * * * * *
Σύνταξη:
CMP reg, reg (3T) CMP reg, mem (9T+ea) CMP
reg, imm (4T) CMP mem, reg (9T+ea) CMP mem,
imm (10T+ea)
I T S Z A P C
* * * * * *
Σύνταξη:
CMPSB
CMPSW
Πραγματοποιεί την σύγκριση (αφαίρεση) του περιεχομένου της διεύθυνσης ES:[DI] από το
περιεχόμενο της DS:[SI], χωρίς να επηρεάζει τις θέσεις αυτές παρά μόνο τα flags. Τα
περιεχόμενα αυτά μπορεί να είναι είτε byte (CMPSB) ,είτε words (CMPSW)
αντίστοιχα. Στην συνέχεια οι SI, DI αυξάνονται κατά 1 (CMPSB) ή 2
68
D I T S Z A P C
Επεκτείνει το bit προσήμου του ΑΧ στον DX. Αυτό γίνεται συνήθως πριν την
προσημασμένη διαίρεση (IDIV).
D I T S Z A P C
? * * * * *
Μετά την πρόσθεση δύο BCD αριθμών μετατρέπει το περιεχόμενο του AL (το
άθροισμα) σε δύο BCD ψηφία.
D I T S Z A P C
? * * * * *
Μετά την αφαίρεση δύο BCD αριθμών διορθώνει το αποτέλεσμα (στον AL), έτσι ώστε
να είναι BCD αριθμός.
DEC Decrement
O D I T S Z A P C
* * * * *
69
Σύνταξη :
Αφαιρεί 1 από την παράμετρο προορισμού είτε αυτή είναι byte ή word. Προσοχή:
Δεν επηρεάζει το carry flag.
O D I T S Z A P C
? ? ? ? ? ?
Σύνταξη :
DIV reg (162T)
DIV mem (168T)
Αν η παράμετρος προορισμού είναι 8μπιτη διαιρεί τον ΑΧ. Το πηλίκο τοποθετείται στον AL
και το υπόλοιπο στον ΑΗ. Αν η παράμετρος είναι 16μπιτη, διαιρεί τον
32μπιτο αριθμό DX:AX, το πηλίκο τοποθετείται στον ΑΧ και το υπόλοιπο στον DX. Αν το
αποτέλεσμα είναι τόσο μεγάλο ώστε να μην χωρά στον αντίστοιχο καταχωρητή,
προκαλείται μια διακοπή τύπου 0 (int 0).
ESC Escape
O D I T S Z A P C
Σύνταξη:
ESC imm, reg
ESC imm, mem
70
Παρέχει μια εντολή και μια προαιρετική παράμετρο στον συνεπεξεργαστή. Η πρώτη
παράμετρος παρέχει τα bits της αντίστοιχης εντολής του συνεπεξεργαστή, ενώ η δεύτερη
είναι ένας καταχωρητής ή μια θέση μνήμης που μπορεί να χρησιμοποιηθεί από τον
συνεπεξεργαστή.
O D I T S Z A P C
Σταματά την λειτουργία της CPU μέχρι να γίνει ένα hardware interrupt. Σημειώστε ότι για
να μπορέσει να συμβεί το τελευταίο, θα πρέπει το Ι flag να είναι 1 (χρήση STI).
O D I T S Z A P C
? ? ? ? ? ?
Σύνταξη:
IDIV reg (184T)
IDIV mem (190T)
O D I T S Z A P C
* ? ? ? ? *
Σύνταξη:
IMUL reg (154T)
IMUL mem (160T)
71
O D I T S Z A P C
Σύνταξη :
Ένα byte εισάγεται στον AL ή μια λέξη στον ΑΧ από την αντίστοιχη θύρα (port), της οποίας
η διεύθυνση δίνεται είτε σαν 8μπιτη σταθερά είτε σαν το 16μπιτο περιεχόμενο του DX.
INC Increment
O D I T S Z A P C
* * * * *
Σύνταξη :
Προσθέτει 1 σε έναν καταχωρητή ή θέση μνήμης. Προσοχή : δεν επιδρά στο carry flag.
O D I T S Z A P C
0 0
Σύνταξη :
72
ΙΝΤ imm
Προκαλεί μια διακοπή software (κλήση κάποιας ρουτίνας του DOS ή του BIOS). Πριν
μεταβεί στην διεύθυνση εξυπηρέτησης της αντίστοιχης διακοπής, σώζει στον σωρό τους
καταχωρητές F (flags), CS και ΙΡ.
O D I T S Z A P C
* *
Σύνταξη :
ΙΝΤΟ
Αν το overflow flag γίνει 1, προκαλείται μια διακοπή ΙΝΤ 4. Το DOS δεν κάνει τίποτε
όταν γίνει ΙΝΤ 4, αλλά μπορεί ο χρήστης να γράψει την δική του ρουτίνα εξυπηρέτησης της
ΙΝΤ 4.
O D I T S Z A P C
* * * * * * * * *
Σύνταξη : IRET
Επιστρέφει από την ρουτίνα εξυπηρέτησης μιας διακοπής. Επαναφέρει από τον σωρό τους
καταχωρητές F (flags), CS και ΙΡ.
D I T S Z A P C
Σύνταξη :
Jcondition shortlabel
Διακλάδωση υπό συνθήκη (condition). Η εντολή αυτή, αν ισχύει η υπό εξέταση συνθήκη,
κάνει ένα σχετικό άλμα (-128 έως +127 θέσεις από την θέση της επόμενης προς εκτέλεση
73
O D I T S Z A P C
Σύνταξη :
JCXZ shortlabel
Όταν ο CX είναι ίσος με μηδέν, γίνεται ένα σχετικό άλμα (-128 έως +127 θέσεις από την
επόμενη εντολή) στην θέση που δίνουμε ως παράμετρο.
JMP Jump
O D I T S Z A P C
Σύνταξη :
JMP shortlabel (15T) JMP reg16 (11T) JMP
nearlabel (15T) JMP mem (18T+ea) JMP
farlabel (15T)
74
O D I T S Z A P C
Σύνταξη : LAHF
I T S Z A P C
Σύνταξη :
LDS reg16, mem32
Παράδειγμα :
LDS BX, fname
Μετά την εκτέλεση της εντολής, ο BX θα έχει ως νέο περιεχόμενο το περιεχόμενο των
θέσεων μνήμης fname, fname +1, και ο DS θα έχει τα περιεχόμενα των θέσεων fname+2,
fname+3.
I T S Z A P C
75
Σύνταξη :
Υπολογίζει και φορτώνει στον αντίστοιχο καταχωρητή το offset της διεύθυνσης του
τελεστή μνήμης mem.
O D I T S Z A P C
Σύνταξη :
LES reg16, mem32
Παράδειγμα :
LES BX, fname
Μετά την εκτέλεση της εντολής, ο BX θα έχει ως νέο περιεχόμενο το περιεχόμενο των
θέσεων μνήμης fname, fname +1, και ο ES θα έχει τα περιεχόμενα των θέσεων fname+2,
fname+3.
O D I T S Z A P C
Σύνταξη :
LOCK instruction
Κατά την διάρκεια εκτέλεσης της εντολής που δίνεται σαν παράμετρος, απαγορεύεται να
λειτουργήσουν άλλοι επεξεργαστές, ώστε να μην αλλάξει κάποιο κομμάτι της μνήμης.
Παράδειγμα :
LOCK ADD AH, 14
76
O D I T S Z A P C
Σύνταξη :
LODS mem
LODSB LODSW
O D I T S Z A P C
Σύνταξη :
LOOP shortlabel
Μειώνει τον CX κατά 1, και εφόσον αυτός δεν έχει γίνει 0, πηγαίνει στο short label
(+127 έως –128 θέσεις από την επόμενη εντολή) που δίνεται σαν παράμετρος.
D I T S Z A P C
Σύνταξη :
LOOPE shortlabel
LOOPZ shortlabel
77
Οι δύο εντολές είναι ακριβώς ίδιες. Μειώνουν τον CX κατά 1 και εφόσον είναι διάφορος του
0 και επιπλέον Ζ=1 κάνουν σχετικό άλμα (-128 έως +127 θέσεις από την επόμενη εντολή).
I T S Z A P C
Σύνταξη :
LOOPNE shortlabel
LOOPNZ shortlabel
Οι δύο εντολές είναι ακριβώς ίδιες. Μειώνουν τον CX κατά 1 και εφόσον είναι διάφορος του
0 και επιπλέον Ζ=0 κάνουν σχετικό άλμα (-128 έως +127 θέσεις από την επόμενη εντολή).
MOV Move
O D I T S Z A P C
Σύνταξη :
MOV reg, reg (2T) MOV reg, imm (4T)
MOV mem, reg (9T+ea) MOV mem, imm (10T+ea)
MOV reg, mem (10T+ea) MOV mem, seg (9T+ea) MOV
reg, seg (2T) MOV seg, mem (8T+ea) MOV
seg, reg (2T)
D I T S Z A P C
Σύνταξη :
78
H MOVSB αντιγράφει ένα byte από την διεύθυνση DS:SI στην ES:DI, και στην συνέχεια
αυξάνει τους SI, DI κατά 1 (αν το flag D=0), αλλιώς τους μειώνει κατά 1 (αν D=1).
Ομοίως, η εντολή MOVSW αντιγράφει ένα word από την DS:SI στην ES:DI και στην
συνέχεια αυξάνει ή μειώνει αντίστοιχα τους SI, DI κατά 2.
O D I T S Z A P C
* ? ? ? ? *
Σύνταξη :
MUL reg (118T) MUL
mem (139T)
NEG Negate
O D I T S Z A P C
* * * * * *
Σύνταξη :
ΝEG reg (3T)
NEG mem (16T+ea)
O D I T S Z A P C
ΝΟΤ Not
O D I T S Z A P C
Σύνταξη :
NOT reg (3T)
NOT mem (16T+ea)
Εκτελεί λογικό ΝΟΤ στην παράμετρο που του δίνουμε, δηλαδή αντιστρέφει όλα τα
bits.
OR Logical OR
O D I T S Z A P C
0 * * ? * 0
Σύνταξη :
OR reg, reg (3T) OR reg, imm (4T)
OR mem, reg (16T+ea) OR mem, imm (17T+ea)
OR reg, mem (9T+ea)
Εκτελεί την πράξη λογικό OR ανάμεσα στις παραμέτρους πηγής και προορισμού (τα ίδιας
τάξης bits γίνονται OR), και το αποτέλεσμα καταχωρείται στην παράμετρο προορισμού.
O D I T S Z A P C
80
Σύνταξη :
OUT imm8, acc (10T) OUT
DX, acc (8T)
Στέλνει ένα byte (AL) ή ένα word (AX) στην θύρα (port) που καθορίζεται είτε άμεσα σαν
ένας αριθμός από 00Η έως FFH, είτε έμμεσα σαν ένας 16μπιτος (0-FFFFH) αριθμός από το
περιεχόμενο του DX.
O D I T S Z A P C
Σύνταξη :
POP reg16 (8T) POP seg (8T) POP
mem16 (17T+ea)
Αντιγράφει την λέξη που βρίσκεται στην κορυφή του σωρού στην 16μπιτη
παράμετρο προορισμού και στην συνέχεια αυξάνει τον SP κατά 2.
O D I T S Z A P C
* * * * * * * * *
Αντιγράφει στον flag register τα δύο bytes που βρίσκονται στην κορυφή του σωρού και
κατόπιν αυξάνει τον SP κατά 2.
O D I T S Z A P C
Σύνταξη :
PUSH reg16 (11T) PUSH seg (10T)
PUSH mem16 (16T+ea)
112
Αφαιρεί 2 από τον SP και αντιγράφει το περιεχόμενο της παραμέτρου προορισμού στο
σημείο που δείχνει ο SP (κορυφή του σωρού).
O D I T S Z A P C
Αφαιρεί 2 από τον SP και αντιγράφει το περιεχόμενο του flag register στο σημείο που
δείχνει ο SP (κορυφή του σωρού).
O D I T S Z A P C
* *
Σύνταξη :
RCL reg, 1 (2Τ) RCL mem, 1 (15Τ+ea)
RCL reg, CL (8T+4*CL) RCL mem, CL (20T+4*CL)
Περιστρέφει αριστερά την παράμετρο προορισμού. Το carry flag γράφεται στο χαμηλότερο
bit, ενώ το υψηλότερο bit αντιγράφεται στο carry flag. Η σταθερά 1 ή ο καταχωρητής CL
μπορεί να χρησιμοποιηθούν σαν μετρητές που θα καθορίσουν τον αριθμό των περιστροφών.
O D I T S Z A P C
* *
Σύνταξη :
RCR reg, 1 (2Τ) RCR mem, 1 (15Τ+ea)
RCR reg, CL (8T+4*CL) RCR mem, CL (20T+4*CL)
O D I T S Z A P C
Επαναλαμβάνει την εντολή χειρισμού string που ακολουθεί τόσες φορές όσο το
περιεχόμενο του CX. Κάθε φορά μειώνει τον CX κατά 1, μέχρι αυτός να γίνει 0.
D I T S Z A P C
*
Λειτουργεί σαν την εντολή REP μόνο εφόσον ισχύει η αντίστοιχη συνθήκη. Οι
REPZ, REPE λειτουργούν όταν zero flag =1, ενώ οι REPNZ, REPNE, όταν Ζ=0.
Το zero flag (Z) επηρεάζεται μόνο από τις εντολές SCAS, CMPS.
O D I T S Z A P C
Σύνταξη :
RET RET imm8
RETN (16T) RETN imm8 (20T) RETF
(26T) RETF imm8 (25T)
114
Επιστροφή από υπορουτίνα. Η RETΝ επιστρέφει από ρουτίνα NEAR, δηλαδή τοποθετεί την
κορυφή του σωρού στον ΙΡ. Η RETF επιστρέφει από ρουτίνα FAR, δηλαδή τοποθετεί την
κορυφή του σωρού στον ΙΡ και στο CS. Η εντολή RET μπορεί να είναι είτε near είτε far,
εξαρτάται το πώς έχει δηλωθεί η αντίστοιχη ρουτίνα. Προαιρετικά, μπορούμε στις εντολές
αυτές να προσθέσουμε έναν 8μπιτο αριθμό, ο οποίος προστίθεται στον SP. Η χρήση της
τελευταίας δυνατότητας είναι σπάνια στην assembly, αλλά έχει σημασία όταν η ρουτίνα μας
χρησιμοποιείται από γλώσσες ανωτέρου επιπέδου (C ή PASCAL). Επίσης η χρήση των
RETN, RETF πρέπει να αποφεύγεται και να χρησιμοποιείται μόνο η RET σε συνδυασμό
με καθορισμό της αντίστοιχης ρουτίνας σαν near ή far.
O D I T S Z A P C
* *
Σύνταξη :
ROL reg, 1 (2T) ROL mem, 1 (15T+ea) ROL reg,
CL (8+4*CL)T ROL mem, CL (20+4*CL)T
O D I T S Z A P C
* *
Σύνταξη :
ROR reg, 1 (2Τ) ROR mem, 1 (15T+ea)
ROR reg, CL (8+4*CL)T ROR mem, CL (20+4*CL)T
Περιστρέφει την παράμετρο προορισμού δεξιά. Το χαμηλότερης τάξης bit αντιγράφεται τόσο
στο carry flag, όσο και στο υψηλότερης τάξης bit. H σταθερά 1 ή ο καταχωρητής CL μπορεί
να χρησιμοποιηθούν σαν μετρητές που να καθορίζουν τον αριθμό των επαναλήψεων της
εντολής αυτής.
115
O D I T S Z A P C
* * * * *
O D I T S Z A P C
* * * ? * *
Σύνταξη :
SAL reg, 1 (2T) SAL mem, 1 (15T+ea)
SAL reg, CL (8+4*CL)T SAL mem, CL (20+4*C L)T
Μετατόπιση όλων των bit της παραμέτρου προορισμού κατά μία θέση αριστερά. Το
υψηλότερης τάξης bit αντιγράφεται στο carry flag και το χαμηλότερης τάξης bit γίνεται 0. H
σταθερά 1 ή το περιεχόμενο του καταχωρητή CL καθορίζουν τον αριθμό των επαναλήψεων
της εντολής. Η εντολή αυτή είναι ίδια με την SHL.
O D I T S Z A P C
* * * ? * *
Σύνταξη :
SAR reg, 1 (2T) SAR mem, 1 (15T+ea)
SAR reg, CL (8+4*CL)T SAR mem, CL (20+4*CL)T
Μετατόπιση όλων των bit της παραμέτρου προορισμού κατά μία θέση δεξιά. Το χαμηλότερης
τάξης bit αντιγράφεται στο carry flag και το υψηλότερης τάξης bit παραμένει στην
προηγούμενη τιμή του. H σταθερά 1 ή το περιεχόμενο του καταχωρητή CL καθορίζουν τον
αριθμό των επαναλήψεων της εντολής.
116
O D I T S Z A P C
* * * * * *
Σύνταξη :
SBB reg, reg (3T) SBB reg, imm (4T)
SBB mem, reg (16T+ea) SBB mem, imm (17T+ea)
SBB reg, mem (9T+ea)
D I T S Z A P C
* * * * * *
Σύνταξη :
SCASB SCASW
SCAS dest
Η εντολή SCASB συγκρίνει το περιεχόμενο του AL με την θέση μνήμης ES:DI και στην
συνέχεια αυξάνει τον DI κατά 1 (αν D flag = 0) ή τον μειώνει κατά 1 (αν D=1). Ομοίως, η
SCASW συγκρίνει τον ΑΧ με περιεχόμενο της θέσης μνήμης ES:DI (2 bytes), και αυξάνει ή
μειώνει αντίστοιχα τον DI κατά 2. Η SCAS χρειάζεται και μια παράμετρο. Αν αυτή είναι
8μπιτη, τότε η SCAS λειτουργεί σαν την SCASB, ενώ αν η παράμετρος είναι 16μπιτη,
λειτουργεί σαν την SCASW.
O D I T S Z A P C
* * * ? * *
Σύνταξη :
SHL reg, 1 (2T) SHL mem, 1 (15T+ea)
SHL reg, CL (8+4*CL)T SHL mem, CL (20+4*CL)T
117
Μετατόπιση όλων των bit της παραμέτρου προορισμού κατά μία θέση αριστερά. Το
υψηλότερης τάξης bit αντιγράφεται στο carry flag και το χαμηλότερης τάξης bit γίνεται 0. H
σταθερά 1 ή το περιεχόμενο του καταχωρητή CL καθορίζουν τον αριθμό των επαναλήψεων
της εντολής. Η εντολή αυτή είναι ίδια με την SAL.
O D I T S Z A P C
* * * ? * *
Σύνταξη :
SΗR reg, 1 (2T) SΗR mem, 1 (15T+ea)
SΗR reg, CL (8+4*CL)T SΗR mem, CL (20+4*CL)T
Μετατόπιση όλων των bit της παραμέτρου προορισμού κατά μία θέση δεξιά. Το χαμηλότερης
τάξης bit αντιγράφεται στο carry flag και το υψηλότερης τάξης bit γεμίζει με το 0 . H σταθερά
1 ή το περιεχόμενο του καταχωρητή CL καθορίζουν τον αριθμό των επαναλήψεων της
εντολής.
O D I T S Z A P C
1
O D I T S Z A P C
1
O D I T S Z A P C
1
I T S Z A P C
Σύνταξη :
STOSB STOS mem
STOSW
Η εντολή STOSB αντιγράφει το περιεχόμενο του AL στην θέση μνήμης ES:DI, και αν
D=0 ο DI αυξάνεται κατά 1, ενώ αν D=1, ο DI μειώνεται κατά 1. Ομοίως, η STOSW
αντιγράφει τον ΑΧ στην θέση ES:DI (2 bytes) και αυξάνει ή μειώνει αντίστοιχα τον DI κατά
2. Η STOS χρειάζεται και μια παράμετρο, το μέγεθος της οποίας (byte ή word), καθορίζει αν
η STOS θα λειτουργήσει σαν την STOSB ή σαν την STOSW.
SUB Subtract
O D I T S Z A P C
* * * * * *
Σύνταξη :
SUB reg, reg (3T) SUB reg, imm (4T)
SUB mem, reg (16T+ea) SUB mem, imm (17T+ea)
SUB reg, mem (9T+ea)
TEST Test
O D I T S Z A P C
0 * * ? * 0
119
Σύνταξη :
TEST reg, reg (5T) TEST reg, imm (4T)
TEST mem, reg (9T+ea) TEST mem, imm (11T+ea)
TEST reg, mem (9T+ea)
Εκτελεί ένα λογικό AND ανάμεσα σε όλα τα ίδια τάξης bit της παραμέτρου προορισμού και
της παραμέτρου πηγής, χωρίς να επηρεάζει τίποτε άλλο παρά μόνο τα flags.
O D I T S Z A P C
Σταματά την λειτουργία της CPU μέχρι ο συνεπεξεργαστής εκτελέσει την τρέχουσα
εντολή του.
XCHG Exchange
O D I T S Z A P C
Σύνταξη :
XCHG reg, reg (4T) XCHG mem, reg (17T+ea)
XCHG reg, mem (17T+ea)
O D I T S Z A P C
XOR Exclusive OR
O D I T S Z A P C
0 * * ? * 0
Σύνταξη :
XOR reg, reg (3T) XOR reg, imm (4T)
XOR mem, reg (16T+ea) XOR mem, imm (17T+ea)
XOR reg, mem (9T+ea)
Κάθε bit της παραμέτρου πηγής γίνεται XOR με το αντίστοιχης τάξης bit της
παραμέτρου προορισμού. Το αποτέλεσμα καταχωρείται στην παράμετρο προορισμού.
120
ΠΑΡΑΡΤΗΜΑ Δ
no input data
related memory:
no input data
related memory:
40:17 = updates keyboard flag byte 0
40:18 = updates keyboard flag byte 1
40:1A = queue head ptr is set to buffer start if Ctrl-Break is
hit
40:1C = updates buffer tail pointer for each keystroke; sets
queue tail ptr is set to queue start if Ctrl-Break is hit
40:1E = updates keyboard buffer (32 bytes)
40:71 = updates bit 7 of the BIOS break flag if Ctrl-Break is
hit
40:72 = updates reset flag with 1234H if Ctrl-Alt-Del pressed
40:96 = indicates keyboard type (AT,PS/2)
40:97 = updates keyboard LED flags (AT,PS/2)
FFFF:0 = reboot code called if Ctrl-Alt-Del pressed
- registers CS, DS, ES, SS, BX, CX, DX are preserved unless
explicitly changed
AH = 00
AL = 00 40x25 B/W text (CGA,EGA,MCGA,VGA)
= 01 40x25 16 color text (CGA,EGA,MCGA,VGA)
= 02 80x25 16 shades of gray text (CGA,EGA,MCGA,VGA)
= 03 80x25 16 color text (CGA,EGA,MCGA,VGA)
= 04 320x200 4 color graphics (CGA,EGA,MCGA,VGA)
= 05 320x200 4 color graphics (CGA,EGA,MCGA,VGA)
= 06 640x200 B/W graphics (CGA,EGA,MCGA,VGA)
= 07 80x25 Monochrome text (MDA,HERC,EGA,VGA)
= 08 160x200 16 color graphics (PCjr)
= 09 320x200 16 color graphics (PCjr)
= 0A 640x200 4 color graphics (PCjr)
= 0B Reserved (EGA BIOS function 11)
= 0C Reserved (EGA BIOS function 11)
= 0D 320x200 16 color graphics (EGA,VGA)
= 0E 640x200 16 color graphics (EGA,VGA)
= 0F 640x350 Monochrome graphics (EGA,VGA)
= 10 640x350 16 color graphics (EGA or VGA with 128K)
640x350 4 color graphics (64K EGA)
= 11 640x480 B/W graphics (MCGA,VGA)
= 12 640x480 16 color graphics (VGA)
= 13 320x200 256 color graphics (MCGA,VGA)
= 8x EGA, MCGA or VGA ignore bit 7, see below
= 9x EGA, MCGA or VGA ignore bit 7, see below
AH = 01
CH = cursor starting scan line (cursor top) (low order 5 bits)
CL = cursor ending scan line (cursor bottom) (low order 5 bits)
126
returns nothing
CGA 25 06 07 08
MDA 25 0B 0C 0E
EGA 25 06 07 0E
EGA 43 04/06 07 08
VGA 25 0D 0E 10
VGA 40 08 09 0A
VGA 50 06 07 08
AH = 02
BH = page number (0 for graphics modes)
DH = row
DL = column
returns nothing
AH = 03
BH = video page
on return:
CH = cursor starting scan line (low order 5 bits)
CL = cursor ending scan line (low order 5 bits)
DH = row
DL = column
- returns data from ~BIOS DATA AREA~ locations 40:50, 40:60 and
40:61
- the ~6845~ can also be used to read the cursor position
- the return data can be circumvented by direct port I/O to the
6845 CRT Controller since this function returns the data found in the
BIOS Data Area without actually checking the controller
AH = 04
on return:
AH = 0 light pen switch not triggered
= 1 light pen triggered
BX = pixel column (0-319 or 0-639, mode dependent)
CH = raster line (0-199) (CGA and EGA modes 4, 5 and 6)
CX = raster line (EGA modes except 4, 5 and 6)
DH = row (0-24)
DL = column (0-79 or 0-79 mode dependent)
AH = 05
AL = new page number
AH = 06
AL = number of lines to scroll, previous lines are
blanked, if 0 or AL > screen size, window is blanked
BH = attribute to be used on blank line
CH = row of upper left corner of scroll window
CL = column of upper left corner of scroll window
DH = row of lower right corner of scroll window
DL = column of lower right corner of scroll window
returns nothing
AH = 07
AL = number of lines to scroll, previous lines are
blanked, if 0 or AL > screen size, window is blanked
BH = attribute to be used on blank line
CH = row of upper left corner of scroll window
CL = column of upper left corner of scroll window
DH = row of lower right corner of scroll window
DL = column of lower right corner of scroll window
returns nothing
AH = 08
BH = display page
on return:
AH = attribute of character (alpha modes only)
AL = character at cursor position
AH = 09
AL = ASCII character to write
BH = display page (or mode 13h, background pixel value)
BL = character attribute (text) foreground color (graphics)
CX = count of characters to write (CX >= 1)
returns nothing
AH = 0A
AL = ASCII character to write
BH = display page (or mode 13h, background pixel value)
BL = foreground color (graphics mode only)
CX = count of characters to write (CX >= 1)
return nothing
130
AH = 0B
BH = palette color ID
= 0 to set background and border color
= 1 to select 4 color palette
BL = color value (when BH = 0)
= palette value (when BH = 1)
- does not work for all EGA and VGA video modes
- sets border color in text mode (BH = 0)
AH = 0C
AL = color value (XOR'ED with current pixel if bit 7=1)
BH = page number
CX = column number (zero based)
DX = row number (zero based)
returns nothing
AH = 0D
BH = page number
CX = column number (zero based)
DX = row number (zero based)
on return:
AL = color of pixel read
- 64K IBM EGAs with BIOS dated 9/13/84 in 350 line video
modes, return invalid data in AL
- page number in BH ignored for 320x200 4 color graphics mode
AH = 0E
AL = ASCII character to write
BH = page number (text modes)
BL = foreground pixel color (graphics modes)
returns nothing
AH = 0F
on return:
AH = number of screen columns
AL = mode currently set
BH = current display page
- video modes greater than 13h on EGA, MCGA and VGA indicate
132
~INT 10,0~ was called with the high bit of the mode (AL) set
to 1, meaning the display does not need cleared
- function returns byte value at 40:49; On EGA, MCGA and
VGA bit 7 of register AL is determined by bit 7 of BIOS Data
Area byte 40:87. This bit is usually set by INT 10,0
with bit 7 of the requested mode (in AL) set to 1
AH = 10h
on return:
BH = value of palette register
on return:
BH = value of border color (overscan register)
on return:
CH = green value
CL = blue value
DH = red value
on return:
ES:DX = pointer to color table provided as input
on return:
BL = value read from video DAC mask register
on return:
BL = current paging mode
CX = current page
AH = 11h
on return:
CX = bytes per character (points)
DL = rows (less 1)
ES:BP = pointer to table
AH = 12h
on return:
BH = 0 if color mode in effect
= 1 if mono mode in effect
BL = 0 if 64k EGA memory
= 1 if 128k EGA memory
= 2 if 192k EGA memory
= 3 if 256k EGA memory
CH = feature bits
CL = switch settings
on return:
AL = 12
on return:
AL = 12
on return:
AL = 12
on return:
AL = 12
BL = 34 cursor emulation
AL = 0 enable cursor emulation
= 1 disable cursor emulation
on return:
AL = 12
on return:
AL = 12
AH = 13h
AL = write mode (see bit settings below)
= 0 string is chars only, attribute in BL, cursor not moved
= 1 string is chard only, attribute in BL, cursor moved
= 2 string contains chars and attributes, cursor not moved
= 3 string contains chars and attributes, cursor moved
BH = video page number
BL = attribute if mode 0 or 1 (AL bit 1=0)
CX = length of string (ignoring attributes)
DH = row coordinate
DL = column coordinate
ES:BP = pointer to string
returns nothing
AH = 14h
AH = 15h
on return:
AX = alternate display adapter type
ES:DI = pointer to parameter table:
AH = 1A
AL = 00 get video display combination
= 01 set video display combination
BL = active display (see table below)
BH = inactive display
on return:
AL = 1A, if a valid function was requested in AH
BL = active display (AL=00, see table below)
BH = inactive display (AL=00)
AH = 1C
on return:
AL = 1C
BX = buffer size in 64 byte blocks
returns nothing
141
returns nothing
no input data
on return:
AX = the number of contiguous 1k memory blocks found at
startup
AH = 00
on return:
AH = keyboard scan code
AL = ASCII character or zero if special function key
143
AH = 01
on return:
ZF = 0 if a key pressed (even Ctrl-Break)
AX = 0 if no scan code is available
AH = ~scan code~
AL = ASCII character or zero if special function key
AH = 02
on return:
AL = BIOS keyboard flags (located in ~BIOS Data Area~ 40:17)
AH = 03
AL = 00 set typematic rate to default
144
returns nothing
AH = 04
AL = 1 for click on
= 0 for click off
AH = 05
CH = ~scan code~
CL = ASCII character
145
on return:
AL = 00 if success
01 if buffer full
INT 16,10 - Extended Wait for Keypress and Read Character (AT+)
AH = 10h
on return:
AH = ~scan code~
AL = ASCII character or zero if special function key
AH = 11h
on return:
ZF = 0 if key pressed (data waiting)
AX = 0 if no scan code is available
AH = ~scan code~
AL = ASCII character or zero if special function key
AH = 12h
on return:
146
AH = 00
CS = PSP segment address
returns nothing
AH = 01
on return:
AL = character from standard input device
AH = 02
DL = character to output
returns nothing
AH = 03
on return:
AL = character from the auxiliary device
AH = 04
DL = character to output
returns nothing
151
AH = 05
DL = character to output
returns nothing
AH = 06
DL = (0-FE) character to output
= FF if console input request
on return:
AL = input character if console input request (DL=FF)
ZF = 0 if console request character available (in AL)
= 1 if no character is ready, and function request
was console input:
AH = 07
on return:
AL = character from STDIN
152
AH = 08
on return:
AL = character from STDIN
AH = 09
DS:DX = pointer to string ending in "$"
returns nothing
AH = 0A
DS:DX = pointer to input buffer
AH = 0B
on return:
AL = 00 if no character available
153
= FF if character available
AH = 0C
AL = 01, 06, 07, 08 or 0A (INT 21 input functions)
on return:
see return values from INT 21,AL where AL is 1, 6, 7, 8 or A
- main function is to clear the input buffer and call INT 21h
with the specified function (in AL)
AH = 0D
returns nothing
AH = 0E
DL = zero based, drive number (0-25, A: - Z:)
on return:
AL = one based, total number of logical drives including
hardfiles (1-26)
AH = 0F
DS:DX = pointer to unopened FCB
on return:
AL = 00 if file opened
= FF if unable to open
AH = 10h
DS:DX = pointer to opened ~FCB~
on return:
AL = 00 if file closed
= FF if file not closed
AH = 11h
DS:DX = pointer to unopened ~FCB~
on return:
AL = 00 if matching file found
= FF if file not found
- FCB must have drive id, filename, and extension before call
- extended FCB can be used to specify a search criteria based
on attributes; hidden, system, label, and directory
attributes can be used to narrow the search
- after successful call DTA holds an unopened ~FCB~/~XFCB~ for
the requested file. Using any of the other FCB functions
destroys this ~DTA~ copy of the FCB/XFCB
- searching can be continued with the FCB find-next function
- "?" wildcard supported after DOS 2.1, "*" supported in DOS
3.x
- DOS 2.x can't find . and .. entries, DOS 3.x can (unless in
root)
AH = 12h
DS:DX = pointer to unopened ~FCB~ returned from
~INT 21,11~ or ~INT 21,12~
on return:
AL = 00 if file found
= FF if file not found
AH = 13h
DS:DX = pointer to an unopened ~FCB~
on return:
AL = 00 if file deleted
= FF if file not found
AH = 14h
DS:DX = pointer to an opened ~FCB~
on return:
AL = 00 if successful read
= 01 if end of file (no data read)
= 02 if ~DTA~ is too small
= 03 if end of file or partial record read
AH = 15h
DS:DX = pointer to an opened ~FCB~
on return:
AL = 00 if write was successful
= 01 if diskette is full or read only
= 02 if ~DTA~ is too small
AH = 16h
DS:DX = pointer to an unopened ~FCB~
157
on return:
AL = 00 if file created
= FF if file creation failed
- creates file using FCB and leaves open for later output
- FCB must be setup with drive id, filename, and extension
before call
AH = 17h
DS:DX = pointer to a modified ~FCB~ of the format:
Offset Description
00 drive designator
01 original file name
09 original file extension
11 new file name
19 new extension
on return:
AL = 00 if file renamed
= FF if file not renamed
AH = 19h
on return:
AL = current default drive (0=A,1=B,etc)
AH = 1A
158
returns nothing
AH = 1B
on return:
AL = sectors per cluster
CX = bytes per sector
DX = clusters on disk
DS:BX = pointer to ~Media Descriptor Byte~ found in ~FAT~
AH = 1C
DL = drive number (0 for default, 1 = A:, Z: = 26)
on return:
AL = sectors per cluster
CX = bytes per sector
DX = clusters on disk
DS:BX = pointer to ~Media Descriptor Byte~ found in ~FAT~
AH = 21h
DS:DX = pointer to an opened ~FCB~
on return:
AL = 00 if read successful
= 01 if EOF (no data read)
= 02 if ~DTA~ is too small
= 03 if EOF (partial record read)
AH = 22h
DS:DX = far pointer to an opened ~FCB~
on return:
AL = 00 if write successful
= 01 if diskette full or read only
= 02 if ~DTA~ is too small
AH = 23h
DS:DX = pointer to an unopened ~FCB~
on return:
AL = 00 if successful
160
AH = 24h
DS:DX = pointer to an opened ~FCB~
returns nothing
AH = 25h
AL = interrupt number
DS:DX = pointer to interrupt handler
returns nothing
AH = 26h
DX = segment address of new ~PSP~
returns nothing
AH = 27h
CX = number of records to read
DS:DX = pointer to an opened ~FCB~
on return:
AL = 00 if read was successful
= 01 if EOF (no data read)
= 02 if ~DTA~ is too small
= 03 if EOF (partial record read)
CX = actual number of records read
AH = 28h
CX = number of records to write
DS:DX = pointer to an opened ~FCB~
on return:
AL = 00 if write successful
= 01 if diskette full or read only
= 02 if ~DTA~ is too small
CX = number of records written
AH = 2A
on return:
162
AH = 2B
CX = year (1980-2099)
DH = month (1-12)
DL = day (1-31)
on return:
AL = 00 if date change successful
= FF if invalid date
AH = 2C
on return:
CH = hour (0-23)
CL = minutes (0-59)
DH = seconds (0-59)
DL = hundredths (0-99)
AH = 2D
CH = hour (0-23)
CL = minutes (0-59)
163
DH = seconds (0-59)
DL = hundredths (0-99)
on return:
AL = 00 if time change successful
= FF if time invalid
AH = 2F
on return:
ES:BX = pointer to current ~DTA~
AH = 30h
on return:
AL = major version number (2-5)
AH = minor version number (in hundredths decimal)
BH = FF indicates MS-DOS, only if OEM vendor chooses to
identify
= 00 indicates PC-DOS
BL:CX = 24 bit OEM serial number if BH is FF
AH = 31h
164
returns nothing
AH = 33h
AL = 00 to get Ctrl-Break checking flag
= 01 to set Ctrl-Break checking flag
= 02 to set extended Ctrl-Break checking
= 05 get boot drive (DOS 4.x)
DL = 00 to set Ctrl-Break checking off
= 01 to set Ctrl-Break checking on
= boot drive for subfunction 5; (1=A:, 2=B:, ...)
on return:
DL = 00 Ctrl-Break checking OFF (AL=0 or AL=2)
= 01 Ctrl-Break checking ON (AL=0 or AL=2)
= boot drive number (1-26, A: - Z:) (function 05)
AH = 35h
AL = interrupt vector number
on return:
ES:BX = pointer to interrupt handler
AH = 36h
DL = drive number (0=default, 1=A:)
on return:
AX = sectors per cluster
= FFFF if drive is invalid
BX = number of available clusters
CX = number of bytes per sector
DX = number of clusters per drive
AH = 39h
DS:DX = pointer to ASCIIZ path name
on return:
CF = 0 if successful
= 1 if error
AX = error code
- creates specified subdirectory
- returns error if directory already exists, element of the
path is not found, directory full or write protected disk
AH = 3A
DS:DX = pointer to ASCIIZ path name
on return:
CF = 0 if successful
= 1 if error
AX = error code
- allows deletion of a subdirectory as long as it exists, is
empty and not the current directory
166
AH = 3B
DS:DX = pointer to ASCIIZ path name
on return:
CF = 0 if successful
= 1 if error
AX = error code if CF set
AH = 3C
CX = file attribute
DS:DX = pointer to ASCIIZ path name
on return:
CF = 0 if successful
= 1 if error
AX = files handle if successful
= error code if failure
AH = 3D
AL = open access mode
00 read only
01 write only
02 read/write
DS:DX = pointer to an ASCIIZ file name
on return:
AX = file handle if CF not set
= error code if CF set
167
AH = 3E
BX = file handle to close
on return:
AX = error code if CF set
- if file is opened for update, file time and date stamp
as well as file size are updated in the directory
- handle is freed
AH = 3F
BX = file handle
CX = number of bytes to read
DS:DX = pointer to read buffer
on return:
AX = number of bytes read is CF not set
= error code if CF set
- read specified number of bytes from file into buffer DS:DX
- when AX is not equal to CX then a partial read occurred due
to end of file
- if AX is zero, no data was read, and EOF occurred before read
AH = 40h
BX = file handle
CX = number of bytes to write, a zero value truncates/extends
the file to the current file position
DS:DX = pointer to write buffer
on return:
AX = number of bytes written if CF not set
= error code if CF set
168
AH = 41h
DS:DX = pointer to an ASCIIZ filename
on return:
AX = error code if CF set
AH = 42h
AL = origin of move:
00 = beginning of file plus offset
01 = current location plus offset
02 = end of file plus offset
BX = file handle
CX = high order word of number of bytes to move
DX = low order word of number of bytes to move
on return:
AX = error code if CF set
DX:AX = new pointer location if CF not set
AH = 43h
AL = 00 to get attribute
= 01 to set attribute
169
AH = 44h
AL = function value
BX = file handle
BL = logical device number (0=default, 1=A:, 2=B:, 3=C:, ...)
CX = number of bytes to read or write
DS:DX = data or buffer
on return:
AX = error code if CF set
AX = # of bytes transferred if CF not set
on return
170
AH = 47h
DL = drive number (0 = default, 1 = A:)
DS:SI = pointer to a 64 byte user buffer
on return:
DS:SI = pointer ASCIIZ directory path string
AX = error code if CF set
AH = 48h
BX = number of memory paragraphs requested
on return:
AX = segment address of allocated memory block (MCB + 1para)
= error code if CF set
BX = size in paras of the largest block of memory available
if CF set, and AX = 08 (Not Enough Mem)
CF = 0 if successful
= 1 if error
AH = 49h
ES = segment of the block to be returned (~MCB~ + 1para)
on return:
171
AH = 4A
BX = new requested block size in paragraphs
ES = segment of the block (~MCB~ + 1 para)
on return:
AX = error code if CF set (see ~DOS ERROR CODES~)
BX = maximum block size possible, if CF set and AX = 8
AH = 4B
AL = 00 to load and execute program
= 01 (Undocumented) create program segment prefix and load
program, but don't execute. The CS:IP and SS:SP of the
program is placed in parameter block. Used by debuggers
= 03 load program only
= 04 called by MSC spawn() when P_NOWAIT is specified
DS:DX = pointer to an ASCIIZ filename
ES:BX = pointer to a parameter block
on return:
AX = error code if CF set
172
AH = 4C
AL = return code (for batch files)
returns nothing
AH = 4D
on return:
AH = system exit code (indicates normal termination)
= 00 for normal termination
= 01 if terminated by ctl-break
= 02 if critical device error
= 03 if terminated by ~INT 21,31~
AL = child exit code
AH = 4E
CX = attribute used during search DS:DX = pointer to ASCIIZ
filespec, including wildcards
on return:
AX = error code if CF set
~DTA~ = data returned from call in the format:
AH = 4F
DS:DX = unchanged from previous function 4E
on return:
AX = error code if CF set
- ~INT 21,4E~ should be called to find the first file and this
function should be called to find all other matching files
- normal files are always included along with files that match
the requested attributes except when the LABEL attribute is
requested. It's up to the programmer to determine which
actually match the requested attributes.
175
AH = 50h
BX = process ID number (process ~PSP~ segment address)
returns nothing
AH = 51h
on return:
BX = process ID
AH = 55h
DX = New PSP segment address
SI = memory size value to place in ~PSP~ offset 02h (DOS 3+)
returns nothing
AH = 56h
DS:DX = pointer to old ASCIIZ path/filename
ES:DI = pointer to new ASCIIZ path/filename
on return:
AX = error code if CF set
AH = 59h
BX = 00 for versions 3.0, 3.1, 3.2
on return:
AX = extended error code (see ~DOS ERROR CODES~)
= 0 if no error
BH = error class
BL = suggested action
CH = locus
AH = 5B
CX = attribute
DS:DX = pointer to ASCIIZ path/filename
on return:
AX = handle if CF not set
177
AH = 5E
AL = 02 set printer setup
BX = redirection list index (see ~INT 21,5F~ AL=2)
CX = length of setup string
DS:SI = far pointer to printer setup string
on return:
AX = error code if CF set, (invalid function)
AH = 5E
AL = 03 get printer setup
BX = redirection list index (see ~INT 21,5F~ AL=2)
ES:DI = far pointer to buffer to receive setup string
on return:
AX = error code if CF set
AH = 5E
AL = 04 set printer setup
BX = redirection list index (see INT 21,5F AL=2)
DX = printer mode to set (bit zero is set for binary mode and
clear for translated/text mode)
on return:
AX = error code if CF set
AH = 5E
178
on return:
AX = error code if CF set
DX = printer mode where bit zero is set for binary mode and
clear for translated mode
AH = 5F
AL = 00
BL = redirection type
= 03 printer
= 04 disk drive
on return:
AX = error code if CF is set
BH = device redirection state
= 00 redirection off
= 01 redirection on
AH = 5F
AL = 01
BH = device redirection state
= 00 turn redirection off
= 01 turn redirection on
BL = redirection type
= 03 printer
= 04 disk drive
on return:
AX = error code if CF is set
AH = 5F
AL = 02
BX = redirection list index
DS:SI = far pointer to a 16 byte buffer to hold device name
ES:DI = far pointer to a 128 byte buffer to hold network name
on return:
AX = error code if CF is set
= 1 invalid function code
= 12 no more files
BH = device status flag,
bit 0 = 0 device valid
bit 0 = 1 device invalid
BL = device type
= 3 printer
= 4 drive
CX = stored parameter value
DS:SI = far pointer to ASCIIZ local device name
ES:DI = far pointer to ASCIIZ network name
AH = 5F
AL = 03
BL = device type
= 3 if printer
= 4 if drive
CX = parameter to save for caller
DS:SI = far pointer to ASCIIZ local device name
ES:DI = far pointer to ASCIIZ network name followed
by ASCIIZ password
180
on return
AX = error code if CF is set
= 1 invalid function code or
invalid source or destination string format or
source device already redirected
= 3 path not found
= 5 access denied
= 8 insufficient memory
AH = 5F
AL = 04
DS:SI = far pointer to ASCIIZ local device name
on return
AX = error code if CF set
= 01 function code invalid
ASCIIZ string is not an existing source device
= 0F redirection paused on server
AH = 62h
181
on return:
BX = segment address of current process
no input data
- function is specified in AX
- a mickey is 1/200 inches
AX = 00
on return:
AX = 0000 mouse driver not installed
FFFF mouse driver installed
BX = number of buttons
AX = 01
returns nothing
183
AX = 02
returns nothing
AX = 03
on return:
CX = horizontal (X) position (0..639)
DX = vertical (Y) position (0..199)
BX = button status
AX = 4
CX = horizontal position
DX = vertical position
returns nothing
AX = 5
BX = 0 left button
1 right button
on return:
BX = count of button presses (0-32767), set to zero after call
CX = horizontal position at last press
DX = vertical position at last press
AX = status
AX = 6
BX = 0 left button
1 right button
on return:
BX = count of button releases (0-32767), set to zero after call
CX = horizontal position at last release
DX = vertical position at last release
AX = status
AX = 7
CX = minimum horizontal position
DX = maximum horizontal position
returns nothing
AX = 8
CX = minimum vertical position
DX = maximum vertical position
185
returns nothing
AX = 9
BX = horizontal hot spot (-16 to 16)
CX = vertical hot spot (-16 to 16)
ES:DX = pointer to screen and cursor masks (16 byte bitmap)
returns nothing
AX = 0A
BX = 00 software cursor
01 hardware cursor
CX = start of screen mask or hardware cursor scan line
DX = end of screen mask or hardware cursor scan line
returns nothing
AX = 0B
on return:
CX = horizontal mickey count (-32768 to 32767)
DX = vertical mickey count (-32768 to 32767)
INT 33,C - Set Mouse User Defined Subroutine and Input Mask
AX = 0C
186
returns nothing
AX = 0F
CX = horizontal ratio (1..32767, default 8)
DX = vertical ratio (1..32767, default 16)
returns nothing
187
AX = 13h
DX = threshold speed (mickeys per second, default 64)
returns nothing
AX = 15h
on return
BX = buffer size need to hold current mouse state
AX = 16h
ES:DX = far pointer to mouse state save buffer
returns nothing
AX = 17h
ES:DX = far pointer to mouse state save buffer
returns nothing
188
AX = 1A
BX = horizontal coordinates per pixel (σ 100)
CX = vertical coordinates per pixel (σ 100)
DX = double speed threshold
returns nothing
AX = 1B
on return:
BX = horizontal coordinates per pixel (σ 100)
CX = vertical coordinates per pixel (σ 100)
DX = double speed threshold
AX = 1F
on return:
AX = 001F if successful
FFFF if error
ES:BX = previous ~INT 33~ vector
189
AX = 20h
returns nothing
- reinstalls the mouse drivers interrupt vectors for INT 10 and
INT 71 (8088/86) and INT 74 (286/386)
AX = 21h
on return:
AX = 0021 mouse driver not installed
FFFF mouse driver installed
BX = 2 mouse driver installed
- similar to ~INT 33,0~ but does not reset the mouse hardware
or
display variables
- both AX and BX must be correct for successful reset
- interrupt routines set through ~INT 33,18~ are preserved
- resets the mouse to the following defaults:
INT 33,24 - Get Driver Version, Mouse Type & IRQ Number
AX = 24h
on return:
BH = major version (see below)
BL = minor version (see below)
CH = mouse type:
= 1 bus mouse
= 2 serial mouse
= 3 InPort mouse
= 4 PS/2 mouse
= 5 Hewlett Packard mouse
CL = IRQ number:
= 0 PS/2
= 2 ~IRQ~ 2
= 5 IRQ 5
= 7 IRQ 7