143 50 35MB
Greek Pages 437 Year 1989
PETER N O RTO N To Βιβλίο της Assembly για τον IBM PC και τους συμβατούς
εκδόσεις
| ΚΛΕΙΔΑΡΙΘΜΟΣ
Τίτλος πρωτοτύπου:
Peter Norton’s Assembly Language Book for the IBM PC
rsci Αποκλειστικότητα για την ελληνική γλώσσα Κ Λ Ε ΙΔ Α Ρ ΙΘ Μ Ο Σ Ιτουρνάρα 27Β Α Θ Η Ν Λ 106 82 Τηλ. 36.32.044 .0EBUG TEST_SE6.EXE «=0000 ΒΧ=0000 CX=0000 0Χ=0000 DS=3985 ES=3985 SS=3996 CS=3995 3995:0000 CD20 INT 20
SP=0050 ΒΡ=0000 SI=0000 D1=0000 IP=0000 NV UP DI PL NZ ΝΑ P0 NC
Οι τιμές των καταχω ρητώ ν SS και CS είναι διαφορετικές από αυτές των DS και ES. Στο πρόγραμμά μας, ορίσαμε δύο τμήματα. Το Τμήμα Στοίβας (STACK SEGMENT) είναι αυτό στο οποίο τοποθετούμε τη στοίβα (STACK). Ορίσαμε το μέγεθος της στοίβας σε 80 byte: Η εντολή DB 10 DUP ("Stack ") λέει στον assembler να μετατρέψει το αλφα ριθμητικό που είναι μέσα σε εισαγω γικά σε byte, και να επαναλάβει το αλφαριθμητικό 10 φορές στη μνήμη. Η DB (Define Byte/Ο ρ ισ μ ό ς Byte) λέει στον assembler ότι καθορί ζουμε byte μνήμης. Εδώ, αρχίζουμε τη δημιουργία της στοίβας με δέκα επαναλήψεις του ASCII κωδικού για το Stack και τρία κενά διαστήματα. Ο κω δικός αυτού είναι 53 74 61 63 6Β 20 20 20, έτσι αν κοιτάξουμε στο τμήμα στοίβας, θα έπρεπε να δούμε αυ τούς τους αριθμούς να επαναλαμβάνονται δέκα φορές. Ζητήστε από το Debug να αντι γράψει αυτή την περιοχή της μνήμης στην οθόνη με την ακόλουθη διαταγή, η οποία λέει στο Debug να αντιγράψει τη μνήμη αρχίζοντας από τη σχετική διεύθυνση 0 μέσα στο τμήμα στοίβας (SS:0):
3996:0000 3996:0010 3996:0020 3996:0030 3996:0040 3996:0050
5374 61 63 6Β 20 20 20-53 5374 61 63 6Β 20 20 20-53 5374 61 63 6B 20 20 20-53 5374 61 63 6B 20 20 20-53 5374 61 63 6B 20 20 20-53 00 00 00 00 00 00 00 00-00
74 61 63 74 61 63 74 61 63 74 61 63 74 61 63 00 00 00
6Β 6Β 6B 6B 6B 00
20 20 20 20 20 00
20 20 20 20 20 00
20 20 20 20 20 00
Stack Stack Stack Stack Stack Stack Stack Stack Stack Stack . .........................
Η διεύθυνση της κορυφής της στοίβας δίνεται από τούς SS:SP. Ο SP είναι ο δείκτης στοίβας (Stack Pointer), ό πω ς ο IP και ο CS για τον κώ δικα, και είναι μια σχετική διεύ θυνση μέσα στο τρέχον τμήμα στοίβας. Στην πραγματικότητα, η "κορυφή της στοίβας" είναι λάθος ονομασία, επειδή η στοί βα αυξάνει από τις υψηλότερες θέσεις μνήμης προς τις χαμηλότερες. Έ τσι, η κορυφή
3985:0000
3996:0000
Εικόνα 11-3. Διάταξη Μνήμης για το TEST
SEG.ΕΧΕ.
της στοίβας είναι στην πραγματικότητα στο κάτω μέρος της στοίβας στη μνήμη, και οι καινούριες καταχωρήσεις στη στοίβα τοποθετούνται προοδευτικά σε χαμηλότερες θέσεις στη μνήμη. Εδώ, ο SP είναι 50h, που είναι ο δεκ αδικ ός 80, επειδή ορίσαμε μια περιοχή στοίβας μήκους 80 byte. Δεν έχουμε τοποθετήσει ακόμα, τίποτε πάνω στη στοίβα, έτσι η κορυφή της είναι ακόμα στην κορυφή της μνήμης που αποταμιεύσαμε γι’ αυτή: στη θέση 50h. Τώρα που γνωρίζετε πώ ς να βρίσκετε τη στοίβα, μπορεί να θέλετε να παρακολουθή σετε πώ ς αυτή μεταβάλλεται στα προγράμματα των προηγούμενων κεφαλαίων. Εδώ όμως, ας συνεχίσουμε με το παράδειγμα που βρίσκεται ήδη στο Debug. Προσέξτε ότι το Τμήμα Στοίβας (SS) είναι το τμήμα με αριθμό 39% (αυτός ο αριθμός ίσως να είναι διαφορετικός στον υπολογιστή σας), ενώ το Τμήμα Κώδικα (CS) είναι στο τμήμα 3995 — ένα λιγότερο από το SS, ή μόνο 16 byte χαμηλότερα στη μνήμη. Αυτό
Το βιβλίο τη ς Assembly για τον IBM PC και τους Συμβατούς
139
σημαίνει ότι αν κάνουμε αποκω δικοποίηση (unassemble) αρχίζοντας από το CS:0, θα δούμε το πρόγραμμά μας (την εντολή INT 20h) ακολουθούμενο από 14 μηδενικά byte (η INT 20h καταλαμβάνει δύο byte), και μετά θα δούμε τα byte από το τμήμα στοίβας. Θα δούμε επίσης, αποκω δικοποιημένα τα δεδομένα του Stack ακολουθούμενα από τρία κενά διαστήματα: -e cs .0 3995:0000 3995:0002 3995:0004 3995:0006 3995:0008 3995:000A 3995:000C 3995:000E 3995:0010 3995:0011 3995:0013 3995:0014 3995:0015 3995:0017 3995:001A 3995:001B 3995:001C 3995:0010 3995:001F
C020 0000 0000 0000 0000 0000 0000 0000 53 7461 63 6B 2020 205374 61 63 6B 2020
INT ADD ADD ADD ADD ADD ADD ADD PUSH JZ DB DB AND AND DB DB DB AND AND
>0 [BX+SI] .AL BX+SI],AL BX+SI],AL BX+SI],AL BX+SI],AL BX+SI].AL BX+SI].AL BX 0074 63 15B [BX+SI].AH [BP+DI+74].DL 61 63 6B [BX+SI] .AH [BP+DI+74]DL
Ό π ω ς ακριβώ ς περιμέναμε, ο αριθμός 53h — ο κω δικός ASCII του S, του πρώτου γρ άμ ματος της περιοχής της στοίβας μας — είναι στη σχετική διεύθυνση 10h (16) μέσα στο τμήμα κώ δικα. Κοιτάζοντας την οθόνη των καταχω ρητώ ν, ίσως να παρατηρήσατε ότι οι κα ταχω ρη τές ES και DS περιέχουν 3985h, 10h λιγότερο από την αρχή του προγράμματος στο τμή μα 3995b. Π ο λλαπλασιάζοντας επί 16 για να πάρουμε τον αριθμό των byte, μπορούμε να δούμε ότι υπάρχουν 100h (256) byte πριν την αρχή του προγράμματος μας. Αυτή εί ναι η ίδια περιοχή που τοποθετείται στην αρχή ενός αρχείου .COM. Μεταξύ άλλω ν, αυτή η περιοχή σημειώ σεω ν των 256 byte στην αρχή των προγραμμά των περιέχει τους χαρακτήρες που πληκτρολογούμε μετά το όνομα του προγράμματος μας. Για παράδειγμα:
«Μ* chsfMstsers qe*YlApf in the! memory dump 3985:0080 3985:0090 3985:OOAO 3985:00B0 3985:00C0
3920 6065 276C 656D 7279
41 20 6C 6F 20
6E 63 20 72 64
64 68 73 79 75
20 61 65 20 6D
6E 72 65 64 70
6F-77 61-63 20-69 75-6D 0D-00
20 74 6E 70 00
66 65 20 0D 00
6F 72 74 20 00
72 73 68 6D 00
20 20 65 65 00
73 77 20 6D 00
6F 6F 6D 6F 00
9 And now fo r so me characters we ’ 11 see in the m emory dump, memo ry dump...............
140
Τ μήματα
Το πρώ το byte μας λέει ότι πληκτρολογήσαμε 39h (ή 57) χαρ ακτήρες, συμπεριλαμβα νομένου του πρώτου κενού διαστήματος, μετά το TEST SEG.EXE. Δεν θα χρησιμο ποιήσουμε αυτές τις πληροφορίες σ ’ αυτό το βιβλίο, αλλά βοηθάει να δείξουμε γιατί μπορεί να θέλατε μια τόσο μεγάλη περιοχή σημειώσεων.
Σημείωση: Η "περιοχή σημειώσεων" ονομάζεται στην πραγμ ατικότητα PSP (Program Segment Prefix/Π ρόθεμα Τ μήματος Π ρογράμματος) και περιέχει πληρο φορίες για χρήση από το DOS. Με άλλα λόγια, δεν πρέπει να σκεφτείτε ότι μπο ρείτε να χρησιμοποιήσετε αυτήν την περιοχή.
Η περιοχή σημειώσεων περιέχει επίσης πληροφορίες που χρησιμοποιεί το DOS όταν βγαίνουμε από ένα πρόγραμμα, είτε με την INT 20h είτε με την INT 21h, λειτουργία 4Ch. Αλλά για λόγους που δεν είναι καθόλου σαφείς, η εντολή INT 20h έχει την απ αίτη ση από τον καταχωρητή CS να δείχνει στην αρχή αυτής της περιοχής σημειώσεων, πράγ μα που αυτός κάνει για ένα πρόγραμμα .COM, αλλά όχι για ένα πρόγραμμα .ΕΧΕ. Αυτό είναι ένα ιστορικό ζήτημα. Και στην πραγμ ατικότητα, η λειτουργία εξόδου (INT 21h, λειτουργία 4Ch) προστέθηκε στο DOS με την εισαγωγή της έκδοσης 2.00. Ο κώ δικας των αρχείων .COM πρέπει να αρχίζει πάντα στη σχετική διεύθυνση 100h του τμήματος κώ δικα, για να αφήνει στην αρχή χώρο για την περιοχή σημειώσεων των 256 byte. Αυτό διαφέρει στο αρχείο .ΕΧΕ, του οποίου ο κ ώ δικ ας άρχιζε από τη θέση IP = 0000, επειδή το τμήμα κώ δικα άρχιζε 100h byte μετά την αρχή της περιοχής στη μνήμη. Θυμηθείτε ότι, στα αρχεία .COM στο Κεφάλαιο 10, έπρεπε οπω σδήποτε να βάζουμε μια ψευδολειτουργία ORG 100h στην αρχή των προγραμμάτω ν μας για να αποταμιεύ σουμε 100h byte. Η ψευδολειτουργία ORG 100h ορίζει την αρχή (origin) του κώ δικά μας στη θέση 100h. Αυτό είναι το μόνο που κάνει, αλλά θα συνεχίσουμε να χρησιμοποιούμε την ORG 100h στα αρχεία μας, επειδή στο υπόλοιπο αυτού του βιβλίου θα χρησιμοποιούμε προγράμματα .COM. Παρουσιάσαμε εδώ ένα αρχείο .ΕΧΕ έτσι ώστε να μπορέσετε να μάθετε για τα τμή ματα. Αργότερα, θα μάθετε περισσότερα γ ι’ αυτά, αλλά από εδώ και στο εξής θα χρη σιμοποιούμε αρχεία .COM, επειδή είναι μικρότερα και φορτώνονται στη μνήμη πιο γρήγορα. Θα δείτε το γιατί όταν θα φτάσουμε στο τελευταίο κεφάλαιο, αλλά τώρα ας προχωρήσουμε. Ας μάθουμε για τις ψευδολειτουργίες των τμημάτων.
Ψευδολειτουργίες Τμημάτων Έχουμε να καλύψουμε αρκετές ψευδολειτουργίες εδώ: τις SEGMENT, ENDS, ASSU ME, και τις NEAR και FAR από την ψευδολειτουργία PROC. Πρέπει επίσης να ρίξου με μια καλύτερη ματιά σ τις εντολές CALL και RET. Ο ταν θα έχουμε καλύψει όλο αυ τό το έδαφος, θα μάθουμε περισσότερα για την εντολή ΙΝΤ και θα δούμε γιατί είναι παρόμοια με την εντολή CALL. Α λλά α ς τις πάρουμε όλες με τη σειρά, αρχίζοντας με τις SEGMENT και ENDS.
Το βιβλίο τη ς Assembly για τον IBM PC καν τους Συμβατούς
Διάταξη μνήμης για πρόγραμμα .ΕΧΕ
Διάταξη μνήμης για πρόγραμμα .COM CS, DS, ES, S S
100h
περιοχή δεδομένων 256 byte
περιοχή δεδομένων 256 byte
DS.ES
CS:IP
Πρόγραμμα, δεδομένα και στοίβα
Πρόγραμμα Τμήμα δεδομένων
SS
SP
141
Περιοχή στοίβας
SP
Εικόνα 11-4. Προγράμματα .COM και .ΕΧΕ.
Οι ψευδολειτουργΐες SEGMENT και ENDS μοιάζουν πολύ με τις ψευδολειτουργΐες PROC και ENDP που συναντήσαμε στο Κεφάλαιο 9. Ορίζουμε ένα τμήμα περικλείον τας μέρος του πηγαίου αρχείου με ένα ζευγάρι SEGM ENT/ENDS, όπω ς ακριβώ ς ορί σαμε μια διαδικασία με το ζευγάρι PR O C /E N D P. Το όνομα πριν από την ψευδολειτουργία SEGMENT είναι μια ετικέτα. Θα χρησιμοποιήσουμε αυτή την ετικέτα στο Κεφάλαιο 13, όταν θα διαιρέσουμε το πηγαίο αρχείο μας σε πολλά διαφορετικά πηγαία αρχεία και σε δύο τμήματα, ένα τμή μα δεδομένων και ένα τμήμα κώ δικα. Με δύο τμήματα, μπορούμε εύκολα να διαχωρί σουμε στη μνήμη τις μεταβλητές από το πρόγραμμά μας. Θα δούμε και άλλα σχετικά με τις μεταβλητές στη μνήμη, στο Κεφάλαιο 13, και θα προσθέσουμε επίσης και άλλα κομμάτια στην ψευδολειτουργία SEGMENT. Υπάρχουν, ωστόσο, μυριάδες λεπτομέρειες, και δεν θα σπαταλήσουμε πολύ χρόνο σ ’ αυτές. Μ πορείτε να βρείτε αυτές τις πληροφο ρίες στο εγχειρίδιο του assembler σας, εάν τις χρειαστείτε.
142
Τ μήματα
Η Ψευδολειτουργία ASSUME Η ψευδολειτουργία ASSUME είναι λίγο πιο περίπλοιαι από τη SEGMENT. Παρέχει στον assembler πληροφορίες για τα τμήματα και για το πώ ς θέλουμε να χρησιμοποιή σουμε τους καταχω ρητές τμήματος. Για να καταλάβουμε την ASSUME, πρέπει να κ α τανοήσουμε πώ ς ο assembler γνωρίζει τη θέση των ετικετώ ν και των ονομάτω ν των μεταβλητών. Κάθε φορά που δημιουργείτε μια ετικέτα, όπω ς μια διαδικασία (π.χ. την WRITE CHAR PROC NEAR) ή μια μεταβλητή μνήμης, ο assembler θυμάται αρκετές πληρο φορίες μαζί με το όνομα: τον τύπο (διαδικασία, byte, λέξη, κ.ο.κ .), τη διεύθυνση του ονόματος, και το τμήμα στο οποίο ορίζεται. Μ ’ αυτή την τελευταία πληροφορία σ χετί ζεται η ASSUME. Ο assembler δεν υποθέτει αυτόματα ότι όλες οι διαδικασίες ενός προγράμμ ατος βρί σ κονται στο ίδιο τμήμα. Σε πολλές περιπτώσεις, όπω ς π.χ. σε μεγάλα προγράμματα σαν το Lotus 1-2-3, δεν βρίσκονται στο ίδιο τμήμα. Τέτοια προγράμματα στην πρα γμ α τικότητα χρησιμοποιούν πολλά διαφορετικά τμήματα κώ δικα. Έ τσ ι προς το συμφέρον της γενικότητας, πρέπει να παρέχουμε πληροφορίες στον assembler με τη μορφή εντο λών ASSUME, που λένε στον assembler σε ποια τμήματα δείχνουν οι καταχω ρητές τμήματος. Για παράδειγμα, ας ρίξουμε μια ματιά στην εντολή ASSUME που χρησιμοποιήσαμε σε προηγούμενα κεφάλαια: ASSUME CS:CODE_SEG
Αυτή η εντολή ASSUME λέει στον assembler ότι ο κα ταχω ρητής CS δείχνει στο τμήμα κώ δικα που ονομάσαμε CODE SEG. Χωρίς αυτές τις πληροφορίες, ο assembler θα "σηκώσει τα χέρια ψηλά" όποτε προσπαθήσουμε να χρησιμοποιήσουμε μια ετικέτα (ό πω ς στην εντολή CALL W R IT E _C H A R ), λέγοντας ότι δεν γνωρίζει σε ποιο τμήμα βρι σ κόμαστε αυτή τη στιγμή με το μήνυμα No or unreachable CS/Δ εν υπάρχει ο CS ή δεν έχω πρόσβαση σ ' αυτόν). Αφού ο καταχω ρητής CS δείχνει πάντα στον κώ δικα που εκτελούμε, μπορεί να φαί νεται λίγο παράξενο που ο assembler παραπονιέται όταν δεν έχουμε εντολή ASSUME. Στην πραγματικότητα, δεν θα χρειαζόμασταν την ψευδολειτουργία ASSUME, εάν δεν υπήρχαν αυτά που λέγονται υπερβάσεις τμη μάτω ν (segment overrides). Ο 8088, κανονικά, διαβάζει δεδομένα (όπω ς στη MOV AI.,SOM E VARIABLE) από το τμήμα δεδομένων (DS). Αλλά μπορεί επίσης να διαβάσει πληροφορίες από οποιοδήποτε άλλο τμήμα, ό πω ς από το τμήμα κώ δικα (CS), χρησιμοποιώντας μία υπέρβαση τμήματος. Α υτός είναι και ο λόγος για τον οποίο ο assembler χρειάζεται την ψευδολειτουργία ASSUME: για να γνωρίζει ποιον καταχωρητή τμήματος να χρησιμοποιήσει ό ταν διαβάζετε ή γράφετε στη μνήμη. Μην ανησυχείτε αν δεν καταλάβατε καλά αυτή την εξήγηση της ψευδολειτουργίας ASSUME. Θα την χρησιμοποιήσουμε ελάχιστα, μέχρι να φτάσουμε στο Κεφάλαιο 29. Εκεί, θα μάθουμε περισσότερα, τόσο για την ψευδολειτουργία ASSUME όσο και για τις υπερβάσεις τμήματος, όταν θα δούμε τα προγράμματα πολλαπλώ ν τμημάτων.
Το βιβλίο τη ς Assembly για τον IBM PC και τους Συμβατούς
143
Οι υπόλοιπες πληροφορίες αυτού του κεφαλαίου είναι απλά για την πληροφόρησή σας, αφού δεν θα τις χρησιμοποιήσουμε σ ’ αυτό το βιβλίο. Μ πορείτε να παραλείψετε τις επό μενες δύο παραγράφους και να τα διαβάσετε αργότερα εάν τα βρείτε δύσκολα ή εάν είστε ανυπόμονοι να επιστρέψετε στον προγραμματισμό.
Κοντινές και Μακρινές Κλήσεις Ας πάμε πίσω για λίγο, και α ς ρίξουμε μια καλύτερη ματιά στις εντολές CALL που χρησιμοποιήσαμε σε προηγούμενα κεφάλαια. Ειδικά, α ς ρίξουμε μια ματιά στο μικρό πρόγραμμα του κεφαλαίου 7, όπου πρω τομάθαμε για την εντολή CALL. Τότε, γρ άψ α με ένα πολύ μικρό πρόγραμμα που έμοιαζε με το πα ρακάτω (χωρίς τη διαδικασία στη θέση 200h):
3985:0100 3985:0102 3985:0105 3985:0108 3985:010Α
Β241 Β90Α00 E8F800 E2FB CD20
MOV MOV CALL LOOP INT
DL.41 CX.000A 0200 0105 20
Μπορείτε να καταλάβετε κοιτάζοντας τον κώ δικα μηχανής στο αριστερό μέρος, ότι η εντολή CALL κα ταλαμβάνει μόνο τρία byte (E8F800). Το πρώ το byte (E8h) είναι η εντολή CALL, και τα υπόλοιπα δύο byte είναι μια σχετική διεύθυνση. Ο 8088 υπολογίζει τη διεύθυνση της ρουτίνας που καλούμε, προσθέτοντας αυτή τη σχετική διεύθυνση 00F8h (θυμηθείτε ότι ο 8088 αποθηκεύει το byte χαμηλής τάξης μιας λέξης στη μνήμη πριν από το byte υψηλής τάξης, έτσι πρέπει να αντιστρέψουμε τα byte) στη διεύθυνση της επόμε νης εντολής (108h στο πρόγραμμά μας). Σ ’ αυτή την περίπτωση λοιπόν, έχουμε F8h + 108h = 200h. Αυτό ακριβώ ς που περιμέναμε. Το γεγονός ότι αυτή η εντολή χρησιμοποιεί μια μόνο λέξη για τη σχετική διεύθυνση, σημαίνει ότι οι κλήσεις περιορίζονται σε ένα μόνο τμήμα, το οποίο έχει μήκος 64Κ byte. Πώς μπορούμε λοιπόν να γράψουμε ένα πρόγραμμα σαν το Lotus 1-2-3 που είναι μεγα λύτερο από 64Κ; Μ πορούμε, χρησιμοποιώ ντας μακρινές (FAR), αντί για κοντινές (NEAR), κλήσεις. Οι κοντινές κλήσεις, όπω ς έχουμε δει, περιορίζονται σε ένα μόνο τμήμα. Με άλλα λόγια, αλλάζουν τον καταχωρητή IP χωρίς να επηρεάζουν τον καταχωρητή CS. Και γι’ αυτό το λόγο, είναι μερικές φορές γνωστές σαν ενδοτμ ημα ηκ ές (intrasegment) κλήσεις. Αλλά μπορούμε επίσης να έχουμε μακρινές κλήσεις, που αλλάζουν τόσο τον κ α τα χωρητή CS όσο και τον IP. Τ έτοιες κλήσεις είναι συνήθως γνω στές σαν δ ια τμη μα τικές (intersegment) κλήσεις επειδή καλούν διαδικασίες που βρίσκονται σε άλλα τμήματα. Αυτές τις δύο μορφές της εντολής CALL τις συνοδεύουν δύο μορφές της εντολής RET. Η κοντινή κλήση, όπω ς είδαμε στο Κεφάλαιο 7, εισάγει μια μόνο λέξη μέσα στη στοίβα για τη διεύθυνση επιστροφής της. Και η αντίστοιχη εντολή RET εξάγει αυτή τη λέξη από τη στοίβα και τη βάζει στον καταχωρητή IP. Στην περίπτωση των Δ ιατμηματικώ ν Κλήσεων και Επιστροφών, μια λέξη δεν είναι
144
Τμήματα
αρκετή, επειδή έχουμε να κάνουμε με κάποιο άλλο τμήμα. Με άλλα λόγια, πρέπει να αποθηκεύσουμε στη στοίβα μια διεύθυνση επιστροφής δύο λέξεων: μια λέξη για τον δεί κτη εντολής (IP) και μια άλλη για το τμήμα κώ δικα (CS). Η Δ ιατμηματική Επιστροφή έπειτα, εξάγει δύο λέξεις από τη στοίβα — τη μία για τον καταχωρητή CS, και την άλ λη για τον IP. Τώρα ερχόμαστε σε ένα λεπτό θέμα. Π ώς ξέρει ο assembler ποιές από αυτές τις CALL και RET να χρησιμοποιήσει; Π ότε πρέπει να χρησιμοποιήσει την FAR CALL, και πότε πρέπει να χρησιμοποιήσει τη NEAR CAL.L; Αυτό είναι το σημείο στο οποίο παίρνουν τον έλεγχο οι ψευδολειτουργίες NEAR και FAR. Για παράδειγμα, δείτε το επόμενο πρόγραμμα: PROC ONE
PROC
PROCJM
ENDP
PROC TVO
ENDP
FAR
PROC_TWO PROC NEAR CALL P R O C O N E
To Make έχει περιορίσει στο ελάχιστο την αναγκαία δουλειά για να ξανακω δικοποιήσουμε το πρόγραμμά μας.
184
Α ντιγράφοντας ένα Τομέα Δίσκου στην Οθόνη
Εάν δεν έχετε κάποια πρόσφατη έκδοση του Macro Assembler της Microsoft, που πε ριλαμβάνει το Make, θα διαπιστώσετε ότι το πρόγραμμα αυτό αξίζει το κόστος μίας αναβάθμισης (upgrade). Θ α πάρετε επίσης κι ένα καλό πρόγραμμα που θα αντικ ατα στήσει το του Debug. Ο νομάζεται Symdeb (Symbolic Debugger/Σ υ μ β ο λικό ς Διορθω τής λαθών), και θα του ρίξουμε μια αργότερα. Τώρα, ας συνεχίσουμε με το Dskpatch.
Μ παλώνοντας το Disp
sec
To D isp_sec, όπω ς το αφήσαμε, περιλάμβανε μια έκδοση της D IS P _ H A L F _ S E CTOR, την οποία χρησιμοποιήσαμε σαν διαδικασία ελέγχου, και την κύρια διαδικ α σία. Τώρα, θα αλλάξουμε την DISP HA LF SECTOR, σε μια συνηθισμένη διαδικ α σία έτσι ώ στε να μπορούμε να την καλέσουμε από κάποια άλλη που θα την ονομάσουμε Disk io. Η διαδικασία ελέγχου μας θα είναι στην Disk io, μαζί με μια δοκιμαστική έκδοση της διαδικασίας που διαβάζει ένα τομέα του δίσκου. Π ρώτα, α ς τροποποιήσουμε τη Disp sec για να την κάνουμε ένα αρχείο με διαδικα σίες, όπω ς κάναμε με τη Video io. Μ ετονομάστε την END DISP HALF SECTOR απλά σε END, αφού η κύρια διαδικασία μας θα είναι τώρα στην Disk io. Έ πειτα α φαιρέστε την εντολή ORG 100h από την CODE SEG, επειδή και πάλι τη μεταφέραμε σε άλλο αρχείο. Αφού σχεδιάζουμε να μεταφέρουμε έναν τομέα στη μνήμη αρχίζοντας από το SECTOR, δεν υπάρχει ανάγκη να δώσουμε δο κιμασ τικά δεδομένα. Μ πορούμε να αντικατασ τή σουμε όλες τις 16 εντολές DB μετά τη SECTOR με μια γραμμή: SECTOR
DB
8192 DUP (0)
η οποία δεσμεύει 8192 byte για την αποθήκευση ενός τομέα. Αλλά θυμηθείτε την προηγούμενη δήλωσή μας ότι οι τομείς έχουν μήκος 512 byte. Γιατί λοιπόν χρειαζόμαστε τόσο μεγάλη περιοχή αποθήκευσης; Υπάρχουν μερικοί σκλη ροί δίσκοι (300 megabyte, για παράδειγμα) που χρησιμοποιούν πολύ μεγάλα μεγέθη το μέων. Αυτά τα μεγέθη δεν είναι συνηθισμένα, αλλά εμείς παρόλα αυτά θέλουμε να είμαστε βέβαιοι ότι δεν θα διαβάσουμε ένα τομέα που θα είναι υπερβολικά μεγάλος για να χωρέσει στη μνήμη που έχουμε δεσμεύσει για το SECTOR. Έ τσι, για λόγους ασφάλειας, έ χουμε δεσμεύσει 8192 byte για το SECTOR. Στο υπόλοιπο αυτού του βιβλίου, με εξαίρεση το SECTOR, το οποίο θα καλύψουμε εν συντομία, θα υποθέσουμε ότι οι τομείς έχουν μήκος μόνο 512 byte. Τώρα αυτό που χρειαζόμαστε είναι μια καινούργια έκδοση της DISP HALF SE CTOR. Η παλιά έκδοση δεν είναι τίποτα περισσότερο από μια διαδικασία ελέγχου που τη χρησιμοποιήσαμε για να δοκιμάσουμε τη DISP LINE. Στην καινούργια έκδοση, θα θελήσουμε να δώσουμε μια σχετική διεύθυνση στον τομέα, έτσι ώστε να μπορούμε να εμφανίσουμε 256 byte, αρχίζοντας από οπουδήποτε μέσα στον τομέα. Μ εταξύ άλλων, αυτό σημαίνει ότι θα μπορούσαμε να αντιγράψουμε το πρώ το μισό, το τελευταίο μισό, ή τα ενδιάμεσα 256 byte. Α κόμα μια φορά, θα δώσουμε αυτή τη σχετική διεύθυνση στον
Το βιβλίο τη ς Assembly για τον IBM PC και τους Συμβατούς
DX. Να η καινούργια — και τελική — έκδοση της DISP _ sec. Λ ίσ τα 15-2. PUBLIC EXTRN
HALF
185
SECTOR του Disp
Η Τ ε λ ικ ή Έ κ δ ο σ η τ η ς D IS P -H A L F -S E C T O R σ το D IS P -S E C .A S M DISP_HALF_SECTOR SEND_CRLF:NEAR
DISP_HALF_SECTOR PROC
XOR PUSH PUSH MOV HALF SECTOR: CALL CALL ADD LOOP
DX.DX CX a . 16
;Εμφάνιση 16 γραμμών
DISP LINE SEND CRLF DX, 16 HALF SECTOR
DISP_HALF_SECTOR ENDP
Ας προχωρήσουμε τώρα στη διαδικασία μας που διαβάζει ένα τομέα.
Ανάγνωση ενός Τομέα Σ’ αυτή την πρώτη έκδοση της READ SECTOR θα αγνοήσουμε εσκεμμένα τα λά θη, όπω ς π.χ. όταν δεν υ πάρχει δ ίσκο ς στον οδηγό δισκέτας. Δεν είναι καλή πρακτική, αλλά αυτή δεν είναι και η τελική έκδοση της READ SECTOR. Δεν θα μπορέσουμε να καλύψουμε το χειρισμό λαθών σ ’ αυτό το βιβλίο, αλλά θα βρείτε ρουτίνες χειρισμού λαθών στην τελική έκδοση του Dskpatch. Π ρος το παρόν όμω ς, θέλουμε α π λώ ς να δια βάσουμε έναν τομέα του δίσκου. Να η δοκιμαστική έκδοση του αρχείου DISK IO.ASM: Λ ίσ τα 15-3. Τ ο Ν έο Α ρ χ ε ίο D IS K -IO .A S M CGROUP
C0DE_SEG
GROUP ASSUME
C0DE_SEG, DATA_SEG CS:CGROUP. DS:CGROUP
SEGMENT PUBLIC
186
Α ντιγράφοντας ένα Τομέα Δίσκου στην Οθόνη
Λίστα 15-3. συνέχεια ORG
100h
EXTRN
DISP_HALF_SECTOR:NEAR
Η διαδικασία αυτή δ ιαβάζει τον πρώτο τομέα του δίσκου Α και αντιγράφει στην οθόνη το πρώτο μισό του τομέα αυτού READ SECTOR
POPF XOR
PROC NEAR AL.O CX.l DX.O BX.SECTOR 25h DX.DX
CALL INT READ_SECTOR
DISP_HALF_SECTOR 2 Oh ENDP
C00E_SEG
ENDS EXTRN
SEGMENT PUBLIC SECTOR:BYTE ENDS
END
READ_SECTOR
DATA_SE6 DATA SEG
;Οδηγός Α (αριθμός 0) ;Ανάγνυση 1 μόνο τομέα ;Ανσγνυση του τομέα 0 ;θέση αποθήκευσης του τομέα αυτού ;Ανάγνυση του τομέα ;Αποθήκευση σημαιών στη στοίβα από το DOS ;Καθορισμός σχετικ ής διεύθυνσης 0 μέσα ;στον τομέα ; Εμφάνιση του πρώτου μισού ;Επιστροφή στο DOS
Υπάρχουν τρεις νέες εντολές σ ’ αυτή τη διαδικασία. Η πρώτη: LEA
ΒΧ.SECTOR
μετακινεί τη διεύθυνση, ή τη σχετική διεύθυνση, του SECTOR (από την αρχή της CGROUP) στον καταχω ρητή ΒΧ. To LEA προέρχεται από το Load Effective Address (Φόρτωσε την Ενεργή Διεύθυνση). Μ ετά από την εντολή LEA, το DS:BX περιέχει πλήρη διεύθυνση του SECTOR, και το DOS χρησιμοποιεί αυτή τη διεύθυνση για τη δεύ τερη νέα εντολή, την κλήση INT 25h, όπω ς θα δούμε αφού πούμε πρώ τα λίγα λόγια για το SECTOR. (Στην πραγμ ατικότητα, η LEA φορτώνει τη σχετική διεύθυνση στον καταχωρητή ΒΧ χωρίς να καθορίζει την τιμή του καταχωρητή DS. Πρέπει να εξασφα λίσουμε εμείς ότι ο DS δείχνει στο σωστό τμήμα.) To SECTOR δεν είναι στο ίδιο πηγαίο αρχείο με τη R E A D _SEC TO R . Είναι στο DISP SEC.ASM. Π ώ ς λέμε στον assembler πού βρίσκεται; Χρησιμοποιούμε την ψευδολειτουργία EXTRN: DATA_SEG EXTRN DATA_SE6
SEGMENT PUBLIC SECTOR:BYTE ENDS
Το βιβλίο τη ς Assembly για τον IBM PC και τους Συμβατούς
0000:
187
CGFCUP
OODESEG
DATASEG ?
0381:
_L£A-^SECTfOR
SECTOR
·* --------►
MOV ΒΧ.0381
Εικόνα 15-1. H LEA Φορτώνει την Ενεργή Διεύθυνση.
Αυτή η ομάδα εντολών λέει στον assembler ότι το SECTOR ορίζεται στο DATA SEG, το οποίο είναι σε ένα άλλο πηγαίο αρχείο, και ότι το SECTOR είναι μια μεταβλητή που αντιπροσωπεύει byte (κι όχι λέξεις). Θα χρησιμοποιούμε τέτοιες εντολές EXTRN συχνά στα επόμενα κεφάλαια. Είναι ο τρόπος για να χρησιμοποιούμε τις ίδιες μεταβλητές σε διαφορετικά πηγαία αρχεία. Πρέπει α π λώ ς να προσέχουμε να ορίζουμε μόνο σε μία θέ ση τις μεταβλητές μας. Ας επιστρέφουμε στην εντολή INT 25h. Είναι κλήση μίας ειδικής λειτουργίας του DOS που διαβάζει τομείς ενός δίσκου. Ό τα ν το DOS δέχεται μία κλήση από την εντολή ΙΝΤ
188
Α ντιγράφοντας ένα Τομέα Δίσκου στην Οθόνη
DATA_SEG SEGMENT PUBLIC EXTRN SECTOR:BYTE DATAjSEG ENDS
Μεταβλητή byte. To LIN K θα δώσει τη διεύθυνση & κόνα 15-2. Η Ψευδολατουργία EXTRN.
25h, χρησιμοποιεί τις πληροφορίες που περιέχουν οι κα ταχω ρητές ω ς εξής: AL CX DX DS:BX
Α ριθμός οδηγού δίσκου (0 = Α, 1 = Β , κλπ.) Α ριθμός τομέων που θα διαβάζονται κάθε φορά Αριθμός πρώτου προς ανάγνωση τομέα (ο πρώ τος είναι ο 0) Διεύθυνση μεταφοράς: εκεί θα αποθηκευθούν οι τομείς
Ο αριθμός στον καταχωρητή AL καθορίζει τον οδηγό δίσκου α π ’ όπου το DOS θα δια βάσει τομείς. Αν ο AL είναι 0, οι τομείς θα διαβαστούν από τον οδηγό Α. To DOS μπορεί να διαβάσει περισσότερους από έναν τομείς με κάθε κλήση, και δια βάζει τον αριθμό των τομέων που του καθορίζει ο CX. Εδώ, ορίζουμε τον CX ίσο με ένα, κι έτσι το DOS θα διαβάσει μόνο έναν τομέα των 512 byte. Μ ηδενίσαμε τον καταχωρητή DX, κι έτσι το DOS θα διαβάσει τον πρώ το τομέα του δίσκου. Μπορείτε, αν θέλετε να διαβάζει κάποιο διαφορετικό τομέα, να αλλάξετε τον αριθμό αυτόν. Αργότερα θα το κάνουμε. DS:BX είναι η πλήρης διεύθυνση της περιοχής της μνήμης όπου θέλουμε να αποθη κεύει το DOS τους τομείς που διαβάζει. Στην περίπτωση αυτή, έχουμε τοποθετήσει στο DS:BX τη διεύθυνση του SECTOR, έτσι ώστε να μπορούμε να καλέσουμε την DISP _H A L F__SE C T O R για να αντιγράψει στην οθόνη το πρώ το μισό του πρώτου τομέα που διαβάστηκε από το δίσκο του οδηγού Α. Τέλος, θα παρατηρήσετε μία εντολή PO PF αμέσω ς μετά την INT 21h. Ό π ω ς αναφέ ραμε και πριν, ο 8088 έχει ένα καταχωρητή που ονομάζεται κα ταχω ρητής κα τάστασης και περιέχει τις διάφορες σημαίες, όπω ς τις σημαίες μηδενός και κρατουμένου. Η POPF είναι μία ειδική περίπτωση της εντολής PO P, που ανασύρει μία λέξη από τον κ α τα χω ρητή κατάστασης. Για ποιο λόγο χρειαζόμαστε την εντολή αυτή; Η εντολή INT 25h αποθηκεύει στη στοίβα, πρώ τα τον καταχωρητή κατάστασης και κατόπιν τη διεύθυνση επιστροφής. Ο ταν το DOS επιστρέψει από την εντολή INT 25h, αφήνει τον καταχωρητή κα τάστασης στη στοίβα. Αυτό το κάνει για να μπορεί να θέσει τη σημαία κρατουμένου ίση με 1 στην επιστροφή, αν έχει συμβεί κάποιο σφάλμα χειρι
Τ ο βιβλίο τη ς Assembly για τον IBM PC και τους Συμβατούς
189
σμού του δίσκου, όπω ς προσπάθεια ανάγνω σης από τον οδηγό Α χωρία να υπάρχει δι σκέτα. Δεν θα κάνουμε έλεγχο λαθών στο βιβλίο αυτό, αλλά πρέπει να αφαιρέσουμε τον καταχωρητή κατάστασης από τη στοίβα — γ ι’ αυτό χρειαζόμαστε την εντολή POPF. (Σημείωση: Η INT 25h , μαζί με την INT 24h που γράφει σε έναν τομέα δίσκου, είναι οι μόνες ρουτίνες του DOS που αποθέτουν τον καταχω ρητή κα τάστασης στη στοίβα.) Τώρα μπορείτε να κωδικοποιήσετε την DISK IO _A SM , και να κωδικοποιήσετε πάλι την DISK SEC ASM. Κατόπιν, συνδέστε τα τέσσερα αρχεία Disk io, D isk_sec, Video io, και Cursor, με το Disk io πρώ το στη λίστα. Ή , αν έχετε το πρόγραμμα Make, προσθέστε αυτές τις δύο γραμμές στο αρχείο Dskpatch: disk_1o.obj:
d1sk_1o.asa
■asa d1sk_1o;
και αλλάξτε τις τρεις τελευταίες γραμμές, σε: d1sk_1o.cs·: d1sk_1o.obj disp_sec.obj video_1o.obj cursor.obj link d1sk_1o disp_sec video_io cursor; exe2b1n d1sk_1o d1sk_1o.cc·· Αφού δημιουργήσετε την έκδοση .COM του Disk io, πρέπει να δείτε στην οθόνη σας κάτι σαν αυτό που παρουσιάζει η Εικόνα 15-3. Θα επιστρέφουμε αργότερα για να προσθέσουμε κι άλλα στο Disk io, για τώρα αρ κετά. Στο επόμενο κεφάλαιο, θα κατασκευάσουμε μία καλύτερη απεικόνιση τομέα προA H lsk Ιο ΕΙ 21 90 49 12 70 00 D0 IB 00 00 C4 12 79 0E 09 02 0Ε CS OS IF 23 7C 19 Α2 27 00 IF Ε0 40 E0 00 00 5F BE 73 11 01 90 90 00 03 Cl 40 A1 11 00 B1 6F 01 E8 39 F7 26 0B 00 00 Ε4 03 74 09 01 EB SS
42 02 SC IE D5 01 70 00 01 Γ3 F7 04 00 03 04 90
4D FI 00 IE 1C 00 00 EB 19 A6 FI D3 EB DB FE 01
20 02 33 00 00 F3 IB 86 0B 75 80 EO 64 SA C4 06
20 00 ED 0C 7C A4 23 00 00 57 3E E8 00 EB 8A IE
33 09 B0 06 51 IF 7C BB 90 26 71 3B 2B E9 CC 00
2E 00 C0 20 FC OB AB 00 F3 0B 01 00 F0 CD SB 11
31 02 07 00 IE 0E 91 05 A6 47 60 FF 76 11 58 2E
00 00 0E 00 36 2C AB 53 75 1C 75 36 0D B9 FF 20
02 00 DO 16 CS 00 A1 BO 62 99 02 IE EO 02 2E 00
02 00 33 22 36 A0 16 01 03 0B BB 00 26 00 6F C3
01 00 C9 00 70 10 00 E8 C7 0E 14 C4 00 D3 01 A1
00 00 0A ...-S.ahL.st3, B1 .ί. .ί." .| 00 . W . I ' 00 11 6 \· ,χ .ι « Ι * ι * ί .. Τ AB IS OB |.i£ i* u W IT G .8 T .. 96 IE 6. 52 E0 BE IB
rs p iii
Ιΰκόνα 15-3: Αντίγραφο Μνήμης στην Οθόνη, από την DISK
,μ.
IO.COM.
190
Αντιγράφοντας ένα Τομέα Δίσκου στην Οθόνη
σθέτοντας μερικούς χαρακτήρες γραφικώ ν, και στη συνέχεια μερικές ακόμη πληρο φορίες.
Περίληψη Τώρα που έχουμε τέσσερα διαφορετικά αρχεία, το Dskpatch αρχίζει να γίνεται λίγο πιο περίπλοκο. Στο κεφάλαιο αυτό γνω ρίσαμε το πρόγραμμα Make, που μας βοηθάει να κάνουμε τη ζωή μας ευκολότερη κω δικοποιώντας μόνο τα αρχεία που έχουμε αλλάξει. Γράψαμε επίσης μία καινούργια διαδικασία, την DISK ΙΟ. Βρίσκεται σε διαφορετι κό πηγαίο αρχείο από το SECTOR, έτσι χρησιμοποιήσαμε τον ορισμό EXTRN στο αρ χείο DISK ΙΟ.ASM για να δώσουμε πληροφορίες στον assembler για το SECTOR, και να του πούμε ότι είναι μεταβλητή byte. Μ άθαμε ακόμη για την εντολή LEA (Φόρτωση Ενεργής Διεύθυνσης), την οποία χρη σιμοποιήσαμε για να φορτώσουμε τη διεύθυνση του SECTOR στον καταχωρητή ΒΧ. Η DISK ΙΟ χρησιμοποιεί ένα νέο αριθμό λειτουργίας, την INT 25h, για να μεταφέρει τομείς από ένα δίσκο στη μνήμη. Τη χρησιμοποιήσαμε για να φορτώσουμε ένα τομέα στη μεταβλητή μνήμης SECTOR, ώστε να μπορούμε να τον αντιγράψουμε στην οθόνη με την D IS P _ H A L F _ S E C T O R . Μ άθαμε επίσης και για την εντολή PO PF που ανασύρει μία λέξη από τη στοίβα και την τοποθετεί στον καταχωρητή κα τάστασης. Χρησιμοποιήσαμε την εντολή αυτή για να αφαιρέσουμε τις σημαίες από τη στοίβα, πράγμα που δεν έκανε το DOS όταν επέ στρεψε από την εντολή INT 25h. Η απεικόνιση μισού τομέα που κατασκευάσαμε δεν είναι ακόμη πολύ θελκτική, αλ λά στο επόμενο κεφάλαιο θα χρησιμοποιήσουμε μερικούς από τους χαρακτήρες γραφι κών του IBM PC για να την κάνουμε πιο ευχάριστη στο μάτι.
16 ΒΕΛΤΙΩΣΗ ΤΗΣ ΟΘΟΝΗΣ ΤΟΥ ΤΟΜΕΑ Προσθήκη Χαρακτήρων Γραφικών 192 Προσθήκη Διευθύνσεων στην Οθόνη 194 Προσθήκη Οριζοντίων Γραμμών 197 Προσθήκη Αριθμών στην Οθόνη 202 Περίληψη 204
19!
192
Βελτίωση της Ο θόνης του Τομέα
^ ^ τ ά σ α μ ε στο τελευταίο κεφάλαιο του Μέρους II. Ό ,τ ι κάναμε μέχρι τώρα ήταν ε φαρμόσιμο στο MS-DOS και στον 8088 (ή στον 8086 και άλλους συγγενείς του 8088). Στο Μ έρος III, θα αρχίσουμε να γράφουμε διαδικασίες ειδικά για τον Π ροσω πικό Υ πο λογιστή IBM και τα κοντινά εξαδέλφια του. Α λλά πριν προχωρήσουμε, θα χρησιμοποιήσουμε αυτό το κεφάλαιο για να προσθέ σουμε μερικές ακόμα διαδικασίες στο Video ίο. Θ α μετατρέψουμε επίσης τη DISP LINE στο Disp sec. Ό λ ε ς οι μετατροπές και οι προσθήκες μας θα γίνουν στην οθό νη. Οι περισσότερες α π ’ αυτές θα γίνουν για να βελτιώσουν την εμφάνιση της οθόνης, αλλά μία θα προσθέσει καινούργιες πληροφορίες: Θα προσθέσει αριθμούς στο αριστερό μέρος, που ενεργούν όπω ς οι διευθύνσεις στην αντιγραφή μνήμης (dump) του Debug. Ας αρχίσουμε με τα γραφικά.
Προσθήκη Χαρακτήρων Γραφικών Ο Προσω πικός Υ πολογιστής IBM έχει μερικούς χαρακτήρες σχεδίασης γραμμών, που μπορούμε να χρησιμοποιήσουμε για να σχεδιάσουμε πλαίσια γύρω από διάφορα τμή ματα της οθόνης αντιγραφής. Θ α σχεδιάσουμε ένα πλαίσιο γύρω από το δεκαεξαδικό μέρος της αντιγραφής, και ένα άλλο γύρω από το μέρος ASCII της αντιγραφής. Αυτή η αλλαγή απαιτεί απλά δουλειά, και πολύ λίγη σκέψη. Δ ώστε τους ακόλουθους ορισμούς κοντά στην αρχή του αρχείου D ISP_SE C .A SM , ανάμεσα στην ψευδολειτουργία ASSUME και στην πρώτη ψευδολειτουργία SEGMENT, αφήνοντας μια ή δύο κενές γραμμές πριν και μετά από αυτούς τους ορισμούς:
Λίστα 16-1. Προσθήκη στην Αρχή του DISP-SEC.ASM Χαρακτήρες γραφικών για το περίγραμμα του τομέα VERTICAL BAR HORIZONTAL BAR UPPER LEFT UPPER RIGHT LOWER LEFT LOWER RIGHT TOP T BAR BOTTOM T BAR TOP TICK BOTTOM TICK
EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU
OBAh OCDh 0C9h OBBh 0C8h OBCh OCBh OCAh OOlh OCFh
Αυτοί είναι οι ορισμοί για τους χαρ ακ τήρ ες γραφικώ ν. Π ροσέξτε ότι βάζουμε ένα μηδέν πριν από κάθε δεκαεξαδικό αριθμό, έτσι ώστε ο assembler να γνωρίζει ότι αυτοί είναι αριθμοί, και όχι ετικέτες. Θ α μπορούσαμε, το ίδιο εύκολα, να είχαμε γράψει δεκαεξαδικούς αριθμούς αντί γι αυτούς τους ορισμούς στη διαδικασία μας, αλλά οι ορισμοί κάνουν τη διαδικασία πιο ευκολονόητη. Για παράδειγμα, συγκρίνετε τις ακόλουθες δύο εντολές:
Το βιβλίο τη ς Assembly για τον IBM PC και τους Συμβατούς
193
Οι περισσότεροι άνθρωποι βρίσκουν την πρώτη εντολή σαφέστερη. Τώρα, να η καινούργια διαδικασία DISP LINE που διαχωρίζει τα διαφορετικά μέρη της οθόνης με το χαρακτήρα VERTICAL BAR, αριθμός 186h (OBAh). Ο πω ς και πριν, οι προσθήκες εμφανίζονται σε γκρι φόντο:
Λ ίστα 16-2. Ο ι Α λ λ α γ έ ς τ η ς D IS P -L IN E σ το D IS P -S E C .A S M DISP LINE PUSH PUSH PUSH
PROC
NEAR
;H σχετική διεύθυνση είναι πιο χρήαιμ ;στον καταχορητή DX ..........................
;Εμφάνιση διαχοριατικού D L/ ’ WRITE CHAR DL.VERTICAL BAR WRITE CHAR
;Σχεδ»αση αριστερής πλευράς περιγράμματος
; Εμφάνιση 16 byte ;Αποθήκευση σχετικής διεύθυνσης για τη ; ρουτίνα ASCII_LOOP ;Ανάγνυση 1 byte ; Εμφάνιση του byte αυτού σε δεκαεξαδικό ; Παρεμβολή ενός κενού μεταξύ τον αριθμόν WRITE_CHAR BX HEX_LOOP
MOV
DL,VERTICAL BAR WRITE CHAR DL.' ' WRITE_CHAR
.•Εμφάνιση διαχοριαπκοώ
CX.16 ;Ανάκτηση σχετικής διεύθυνσης στο SECTOR
;ϊχεδΐασπ δεξιός πλευράς περιγράμματος
194
Βελτίωση της Ο θόνης του Τομέα
Λίστα 16-2. συνέχεια POP RET DISP LINE
ΒΧ ENDP
Κωδικοποιήστε αυτή την καινούργια έκδοση του Disp sec και συνδέστε τα τέσσερα αρχεία σας (θυμηθείτε να τοποθετήσετε το Disk io πρώ το στη λίστα των αρχείων που ακολουθεί τη διαταγή LINK). Θα δείτε ωραίες διπλές γραμμές να χωρίζουν την οθόνη σε δύο μέρη, όπω ς μπορείτε να δείτε στην Εικόνα 16-1.
Προσθήκη Διευθύνσεων στην Οθόνη Τώρα ας δοκιμάσουμε κάτι πιο δύσκολο: Να προσθέσουμε τις δεκαεξαδικές διευ θύνσεις στην αριστερή πλευρά της οθόνης. Αυτοί οι αριθμοί αντιπροσωπεύουν τη σχετι κή διεύθυνση από την αρχή του τομέα, έτσι ο πρώ τος αριθμός θα είναι ο 00, ο επόμενος 10, ο επόμενος 20, κ.ο.κ. Α> d i sk_ i ο ΕΒ 21 90 02 70 00 00 00 80 D2 79 0Ε 02 8Ε C5 BF 23 7C Α2 27 88 Εθ 40 Ε8 00 5Γ BE Β1 0Β 98 00 03 Cl Α1 11 80 6F 01 ΕΒ F7 26 8Β 80 Ε4 83 89 81 ΕΒ
49 D8 C4 89 BE Β9 ΒΓ 88 73 98 48 Β1 39 88 74 55
42 82 5C ΙΕ D5 ΒΒ 78 00 01 F3 F7 04 00 03 84 98
4D FD 88 ΙΕ BC 00 00 ΕΒ Β9 Α6 F1 D3 Ε8
28 82 33 80 08 F3 ΒΒ 86 8Β 75 88 Ε8 64 DB 5Α FE C4 81 86
20 00 ED 8C 7C Α4 23 80 88 57 3Ε Ε8 80 ΕΒ 8Α ΙΕ
33 89 Β0 06 51 1F 7C ΒΒ 90 26 71 3Β 2Β Ε9
2Ε 88 C0 20 FC 88 ΑΒ 00 F3 8Β 81 88 F8
31 02 07 00 ΙΕ 0Ε 91 05 Α6 47 60 FF 76 CD 11 CC 5Β 50 08 11 2Ε
00 00 ΘΕ 00 36 2C ΑΒ 53 75 1C 75 36 0D Β9 FF
02 00 D0 16 C5 00 Α1 Β0 62 99 02 ΙΕ Εθ 02 2Ε
02 0Θ 33 22 36 Α0 16 01 03 ΘΒ ΒΘ 00 26 00 6F
01 0Θ C9 θθ 78 1θ 00 ΕΒ C7 ΘΕ 14 C4 00 D3 01
00 0Θ ΘΑ Β1 ΘΘ θθ D1 ΑΒ 15 ΘΒ 96 ΙΕ 52 Εθ BE
20 00 C3 Α1 18
Εικόνα 16-1. Προσθήκη Κατακορύφων Γραμμών Η πορεία είναι σχετικά απλή, αφού έχουμε ήδη τη διαδικασία WRITE HEX για τη γραφή ενός αριθμού σε δεκαεξαδική μορφή. Α λλά έχουμε ένα πρόβλημα σχετικά με το χειρισμό ενός τομέα μήκους 512 byte: Η W RITE HEX εμφανίζει μόνο διψήφιους δεκαεξαδικούς αριθμούς, ενώ εμείς χρειαζόμαστε τρία δεκαεξαδικά ψηφία για αριθμούς μεγαλύτερους από το 255. Να η λύση. Αφού οι αριθμοί μας θα είναι μεταξύ του μηδενός και του 511 (Oh μέχρι
Το βιβλίο της Assembly για τον IBM PC και τους Συμβατούς
195
IFFh), το πρώ το ψηφίο είτε θα είναι ένα κενό, εάν ο αριθμός (όπω ς π.χ. ο BCh) είναι μικρότερος του 100h, είτε θα είναι μονάδα. Έ τσι, εάν ο αριθμός είναι μεγαλύτερος του 255, θα.εμφανίσουμε απλά τη μονάδα, ακολουθούμενη από το δεκαεξαδικό αριθμό για το byte χαμηλής τάξη ς. Α λλιώ ς, θα εμφανίσουμε πρώ τα ένα κενό. Αυτές είναι οι προ σθήκες στη DISP LINE που θα εμφανίζουν αυτόν τον τριψήφιο δεκαεξαδικό αριθμό: Λ ίστα 16-3. Π ρ ο σ θ ή κ ε ς σ τη D IS P -L IN E σ το D IS P -S E C .A S M DISP LINE PUSH PUSH PUSH MOV
PROC BX CX DX BX.DX
NEAR
MOV
0L,* ’
CMP JB
BX.lOOh WRITEJ)NE
MOV WRITE ONE: CALL MOV
DL.*1* WRITE CHAR Dt,BL~
CALL
WRITE HEX
MOV CALL MOV
D L.' ’ WRITE CHAR DL,VERTICAL BAR
;H σχετική διεύθυνση είναι πιο χρήσιμη ;στον καταχορητή DX ;Αναγραφή διεύθυνσης σε δεκαεξαδικό ;Είναι το πρΰτο φηφίο 1; ;Ό χ ι , εμφάνιση του κενού που βρίσκεται ;ήδη στον καταχορητή DL ;Ηαι, τοποθέτηση Ί ' ατον DL για έξοδο ;Αντιγραφή του byte χαμηλής τάξης του DL ;γισ δεκαεξαδική έξοδο ; Εμφάνιση διαχυριστικού ; Σχεδίαση αριστερής πλευράς περιγράμματοι
Μπορείτε να δείτε το αποτέλεσμα στην Εικόνα 16-2. Πλησιάζουμε περισσότερο στην πλήρη οθόνη μας. Αλλά η απεικόνιση δεν είναι κεντραρισμένη. Πρέπει να τη μετακινήσουμε προς τα δεξιά για περίπου τρία κενά διαστή ματα. Ας κάνουμε αυτή την τελευταία αλλαγή, και έπειτα θα έχουμε την τελική έκδοση της D ISP _L IN E . Θα μπορούσαμε να κάνουμε την αλλαγή κα λώ ντας τη W RITE CHAR τρεις φορές με ένα χαρακτήρα κενού διαστήματος, αλλά δεν θα το κάνουμε. Απεναντίας, θα προ σθέσουμε μια άλλη διαδικασία, που ονομάζεται WRITE CHAR Ν TIMES, στο Video io Ό π ω ς υπονοεί και το όνομά της, αυτή η διαδικασία εμφανίζει ένα χα ρ α κ τή ρα Ν φορές. Δ ηλαδή, τοποθετούμε τον αριθμό Ν στον καταχωρητή CX και τον κω δικό του χαρακτήρα στον DL, και καλούμε τη W RITE CHAR N _ T IM E S να εμφανίσει Ν αντίγραφα του χαρακ τή ρα του οποίου ο κω δικός ASCII είναι τοποθετημένος στον DL. Έ τσι, θα μπορούμε να εμφανίζουμε τρία κενά διαστήματα τοποθετώ ντας το 3 στον CX και το 20h (τον κω δικό ASCII του κενού διαστήματος) στον DL.
196
Βελτίωση της Ο θόνης του Τομέα
ΒΒ 10 20 3Β 40 50 60 70 80 90 Α8 ΒΒ CB DB Ε0 F0
ΕΒ 02 ΒΒ D2 62 BF Α2 ΕΒ ΒΒ Β1 ΒΒ Α1 6F F7 80 89
21 70 00 79 8Ε 23 27 4Β 5F ΒΒ Β3 11 81 26 Ε4 81
9Β ΒΒ ΒΒ BE C5 7C ΒΒ ΕΒ BE 9Β Cl 88 Ε8 ΒΒ 83 ΕΒ
49 DB 04 89 8Ε Β9 BF 8Β 73 98 48 Β1 39 ΒΒ 74 55
42 82 5C ΙΕ D5 ΒΒ 78 ΒΒ 81 F3 F7 84 88 83 84 9Β
4D FD 88 ΙΕ BC 88 ΒΒ ΕΒ Β9 Α6 F1 D3 Ε8 D8 FE 81
28 82 33 88 88 F3 Β8 86 ΒΒ 75 88 Ε8 64 5Α C4 86
28 88 ED BC 7C Α4 23 ΒΒ 88 57 3Ε Ε8 88 ΕΒ ΘΑ ΙΕ
33 89 ΒΒ 86 S1 1F 7C ΒΒ 9Β 26 71 3Β 2Β Ε9 CC 88
2Ε 88 C8 28 FC 88 ΑΒ 88 F3 8Β 81 88 FB CD 5Β 11
31 82 87 88 ΙΕ BE 91 85 Α6 47 68 FF 76 11 58 2Ε
ΒΒ 88 8Ε 88 36 2C ΑΒ 53 75 1C 75 36 BD Β9 FF 28
82 88 D8 16 C5 88 Α1 ΒΒ 62 99 82 ΙΕ Ε8 82 2Ε 88
82 88 33 22 36 ΑΒ 16 81 83 ΒΒ ΒΒ ΒΒ 26 88 6F C3
81 ΒΒ C9 ΒΒ 78 18 88 ΕΒ C7 BE 14 C4 88 D3 81 Α1
88 88 ΒΑ Β1 88 88 D1 ΑΒ 15 ΒΒ 96 ΙΕ 52 Ε8 BE 18
itilB H 3 .1 , •Ρ ·1 . 1 .................... Π - 8 ...Ϊ . .4 ." .| .J W .I Q ' .H * * · 6* . ηχ .ι Ι |! ί ι 1 $ 1 ..Τ .β ι ς ,ι ΐ....s i.it . J . fl £ i» u b i|
l.ih'uU ivc.B v.. 6 ..- . Ο .Ϊ9.Β J .+ = v .8 I.R . .f Z iO - .f l. . gz.t.i-ijix .o .J
a.sufc......... μ.
Α>
Εικόνα 16-2. Προσθήκη Αριθμών στα Αριστερά. Να η διαδικασία που πρέπει να προσθέσουμε στο VIDEO
IO.ASM:
Λ ίσ τα 16-4. Π ρ ο σ θ έσ τε τη Δ ια δ ικ α σ ία α υ τή σ το V ID E O -IO .A S M PUBLIC
URITE_CHAR_N_TIHES
Η διοδικααία αυτή εμφανίζει περισσότερα από ενα αντίγραφα ενό ς χαρακτήρα DL CX Uses:
Κοδικός χαρακτήρα Αριθμός εμφανίαευν
του χαρακτήρα
WRITE_CHAR
URITE_CHAR_N_TIHES PROC PUSH CX N_TIHES: CALL WRITE_CHAR LOOP N_TIMES POP CX RET URITE_CHAR_N_TIMES ENDP
NEAR
Μ πορείτε να δείτε πόσο απλή είναι αυτή η διαδικασία, αφού έχουμε ήδη τη WRITE CHAR. Αν αναρωτιέστε γιατί κάναμε τον κόπο να γράψουμε μια διαδικασία για κ ά τι τόσο απλό, είναι επειδή το πρόγραμμά μας, το Dskpatch, είναι πολύ σαφέστερο όταν καλούμε τη W R IT E _C H A R N _ T IM E S , παρά όταν γράφουμε ένα μικρό βρόχο που εμφανίζει πολλαπλά αντίγραφα ενός χαρακτήρα. Εξάλλου, θα ξαναχρησιμοποιήσουμε αυτή τη διαδικασία αρκετές φορές.
Το βιβλίο της Assembly για τον IBM PC και τους Συμβατούς
197
Να οι αλλαγές στη DISP LINE για να προσθέτει τρία κενά διαστή ματα στα αριστε ρά της οθόνης μας. Κάντε τις αλλα γές στο DISP SEC.ASM: PUBLIC EXTRN EXTRN
DISP LINE WRITE_HEX:NEAR WRITE_CHAR: NEAR
Η διαδικασία αυτή εμφανίζει μία γραμμή δεδομένον. ή 16 byte, πρύτα σε δεκαεξαδικό. και μετά oe ASCII DS:DX
Σχετική διεύθυνση μέσα στον τομέα, σε byte
Reads: SECTOR DISP_LINE PUSH PUSH PUSH ;H σχετική διεύθυνση είναι πιο χρήσιμη ;στον καταχυρητή DX
ν κενόν πριν από τη γραμμή ;Αναγραφή διεύθυνσης σε δεκαεξαδικό ;Εϊναι το πρύτο φηφίο 1; ;'0 χ ι, εμφάνιση του κενού που βρίσκεται ;ήδη στον καταχυρητή DL ;Ναι, τοποθέτηση Ί * στον 0L για έξοδο
Κάναμε αλλαγές σε τρία σημεία. Π ρώτα, έπρεπε να προσθέσουμε μια εντολή EXTRN για τη WRITE CHAR Ν TIMES, επειδή η διαδικασία είναι στο Video io, και όχι σ’ αυτό το αρχείο. Α λλάξαμε επίσης το τμήμα σχολίω ν, για να δείξουμε ότι χρησιμο ποιούμε αυτή την καινούργια διαδικασία. Η τρίτη μας αλλαγή, οι δύο γραμμές που χρη σιμοποιούν τη W RITE CHAR Ν TIMES, είναι αρκετά σαφής και δεν χρειάζεται εξήγηση. Δοκιμάστε αυτή την καινούργια έκδοση του προγράμματός μας για να δείτε πώ ς κεν τράρεται τώρα η οθόνη. Έ π ειτα θα προχω ρήσουμε στην προσθήκη περισσότερων χ α ρακτηριστικών στην οθόνη μας — των πάνω και κάτω γραμμώ ν των πλαισίων μας.
Προσθήκη Οριζοντίων Γραμμών Η προσθήκη οριζοντίων γραμμώ ν στην οθόνη μας δεν είναι τόσο απλή όσο ακούγεται, επειδή έχουμε να λάβουμε υπόψη μερικές ειδικές περιπτώσεις. Έ χουμε τα ά κ ρα , '
198
Βελτίωση τη ς Ο θόνης του Τομέα
όπου οι γ ραμμές πρέπει να σχηματίσουν γωνίες, και έχουμε επίσης συνδέσεις σε σχήμα Τ στο πάνω και κάτω μέρος της διαχω ριστικής γραμμής ανάμεσα στο δεκαεξαδικό παράθυρο και στο παράθυρο ASCII. Θ α μπορούσαμε να γράψουμε μια μακριά λίστα εντολώ ν (με τη W RITE CHAR Ν TIMES) για να δημιουργήσουμε τις οριζόντιες γραμμές μας, αλλά δεν θα το κά νουμε. Έ χουμε έναν πιο σύντομο δρόμο. Θ α εισάγουμε μια άλλη διαδικασία, που ονο μάζεται WRITE PATTERN, η οποία θα εμφανίζει ένα πρότυπο σχέδιο στην οθόνη. Επειτα, αυτό που θα χρειαστούμε είναι μια μικρή περιοχή της μνήμης που θα κρατά την περιγραφή κάθε σχεδίου. Χ ρησιμοποιώντας αυτή την καινούργια διαδικασία, μπο ρούμε επίσης εύκολα να προσθέσουμε γραμμές υποδιαιρέσεων για να υποδιαιρέσουμε το δεκαεξαδικό παράθυρο, όπω ς θα δείτε όταν θα τελειώσουμε αυτό το τμήμα. Η WRITE PATTERN χρησιμοποιεί δύο εντελώς καινούργιες εντολές, τις LODSB και CLD. Θα τις περιγράφουμε αφού πρώ τα δούμε καλύτερα τη W RITE PATTERN και τον τρόπο που ορίζουμε ένα πρότυπο σχέδιο. Π ρος το παρόν, εισάγετε αυτή τη δια δικασία στο αρχείο VIDEO ΙΟ .ASM:
Λίστα 16-5. Προσθέστε τη Διαδικασία αυτή στο VIDEO-IO.ASM PUBLIC
WRITE_PATTERN
Η διαδικασία αυτή εμ φανίζει μία γραμμή ατην οθόνη, με βάση τα α τ ο ιχ εία της φόρμας D6 {χαρακτήρας, αριθμός εμφσνίσευν χαρακτήρα}, 0 ’Οπου { χ} σημαίνει ότι το χ μπορεί να επαναλαμβάνεται α περιό ρ ιστες φορές DS:DX Διεύθυνση της παραπάνυ εντολής δεομένυν Uses:
WRITE_CHAR_N_TIMES
WRITE_PATTERN PUSH PUSH PUSH PUSH PUSHF CLD
;Αποθήκευση της σημαίας διεύθυνσης ;"Σήκομα" της σημαϊος διεύθυνσης ;γ ια την ποσότητα αύξησης ;Μετακίνηση της σχετικ ής διεύθυνσης στον ;κατσχυρητή SI για τη LODSB
AL.AL ENDPATTERN DL.AL
CH.CH WRITE_CHAR_N_TIMES PATTERNLOOP END PATTERN:
;Αποθήκευση δεδομένυν χαρακτήρα στον AL ;Είναι το τέλος τυν δεδομέν«ν (Oh)? ;Ναι, επιστροφή ; ' 0 χ ι , προετοιμασία για εμφάνιση του ;χαρακτήρα Ν φορές ;Ανάκτηαη μετρητή επσναλήφευν από τον AL ;Και αιοθήκευση στον CX για την ;WRITE_CHAR_M_TIMES ;Μηδενικό by te υφηλής τάξης του CX
Το βιβλίο τη ς Assembly για τον IBM PC και τους Συμβατούς
199
Λίστα 16-5. συνέχεια POPF
URITE_PATTERN
;Αποκατάσταση σημαίας διεύθυνσης
ENDP
Πριν δούμε πώ ς δουλεύει αυτή η διαδικασία, ας δούμε πώ ς να γράφουμε δεδομένα προτύπων σχεδίων. Θα τοποθετήσουμε τα δεδομένα για το σχέδιο της πάνω γραμμής στο αρχείο Disp sec, όπου και θα τα χρησιμοποιήσουμε. Σ ’ αυτό το σημείο θα προσθέ σουμε ακόμα μια διαδικασία, που ονομάζεται ΙΝ1Τ SEC DISP, που αρχίζει την α πεικόνιση του τομέα εμφανίζοντας την οθόνη μισού τομέα, και μετά θα τροποποιήσουμε τη READ SECTOR ώστε να καλεί τη διαδικασία IN IT _ S E C _ D 1 S P . Πρώτα, τοποθετήστε τα ακόλουθα δεδομένα αμέσως μετά το SECTOR (στο DISP _SEC.ASM ), μέσα στο τμήμα δεδομένων:
Λίστα 16-6. Προσθήκες στο DISP-SEC.ASM TOP_LINE_PATTERN LABEL BYTE DB '. 7 DB UPPER_LEFT, 1 DB H0RIZ0NTAL_BAR,12 DB TOP_TICK.l DB H0RIZ0NTAL_BAR,11 DB T0P_TICK,1 DB H0RIZ0HTAL_BAR.11 DB T0P_TICK,1 DB H0RIZ0NTALBAR,12 DB TOPTBAR, 1 DB H0RIZ0NTAL_BAR,18 DB UPPER_RI6HT,1 DB 0 B0TT0H_LINE_PATTERN LABEL BYTE DB ' \7 DB L0WER_LEFT,1 DB H0RIZ0NTAL_BAR,12 DB B0TT0MTICK.1 DB H0RIZ0NTAL_BAR,11 DB BOTTOMTICJC, 1 DB H0RIZ0NTAL_BAR,11 DB B0TT0HTIDC.1 DB H0R1Z0NTALBAR,12 DB B0TT0HTBAR.1 DB H0RIZ0NTAL_BAR,18 DB L0WER_RIGHT,1 DB 0
Κάθε εντολή DB περιέχει μέρος από τα δεδομένα μιας γραμμής. Το πρώτο byte είναι ο προς εμφάνιση χαρ ακ τήρ ας, το δεύτερο byte λέει στη W R 1TE _PA TER N πόσες φο
200
Βελτίωση της Ο θόνης του Τομέα
ρές να επαναλάβει αυτό το χαρακτήρα. Για παράδειγμα, αρχίζουμε την πάνω γραμμή με επτά κενά διαστήματα, ακολουθούμενα από ένα χαρακτήρα για την πάνω αριστερή γωνία, ακολουθούμενο από δώ δεκα χαρακτήρές οριζόντιας μπάρας, κ.ο.κ . Η τελευ ταία DB είναι ένα μοναδικό δεκαεξαδικό μηδενικό, το οποίο σημειώνει το τέλος του σχεδίου. Ας συνεχίσουμε τις μετατροπές μας και α ς δούμε το αποτέλεσμα πριν ασχοληθούμε με τις εσωτερικές διεργασίες της W RITE PATTERN. Να η δοκιμαστική έκδοση της IN IT SEC DISP. Αυτή η διαδικασία εμφανίζει το σχέδιο της πάνω γραμμής, την ο θόνη μισού τομέα, και τέλος το σχέδιο της κάτω γραμμής. Τοποθετήστε την στο αρχείο DISP SEC.ASM, αμέσω ς πριν τη D IS P _ H A L F _ S E C T O R : Λ ίσ τα 16-7. Π ρ ο σ θ έσ τε τη Δ ια δ ικ α σ ία α υ τή σ το D IS P -S E C .A S M PUBLIC EXTRN
ΙΝΙΤ SEC DISP YRITE_PATTERN: NEAR, SEND_CRLF: NEAR
Η διαδικαοϊα αυτή ετοιμάζει την απεικόνιση του μισού τομέα Uses: Reads:
WRITE_PATTERN, SENDCRLF, DISP_HALF_SECTOR TOP_LINE_PATTERN, B0TT0M_LINE_PATTERN
INIT_SEC_DISP PUSH
PROC NEAR DX DX. T0P_LINE_PATTERN WRITE_PATTERN SEND_CRLF DX.DX DISP_HALF_SECTOR DX, BOTTOMLI NE_PATTERN WRITE_PATTERN DX
INIT_SEC_DISP
ENDP
Χρησιμοποιήσαμε την εντολή LEA για να φορτώσουμε μια διεύθυνση στον κα ταχω ρη τή DX, έτσι η W RITE PATTERN γνωρίζει πού να βρει τα δεδομένα του προτύπου σχεδίου. Τέλος, πρέπει να κάνουμε μια μικρή αλλαγή στη READ SECTOR στο αρχείο DISK ΙΟ. ASM, για να καλεί την IN IT _SE C TO R DISP, αντί για τη W RITE HALF _ S E C T O R DISP, έτσι ώστε να σχεδιαστεί ένα πλήρες πλαίσιο γύρω από την οθόνη μας του μισού τομέα: Λ ίσ τα 16-8. Ο ι Α λ λ α γ έ ς τ η ς R E A D - S E C T O R σ το D IS K -IO .A S M
; Η διαδικασία αυτή διαβάζει τον πρϋτο τομέα τι)υ δϊσκιου Α κ(]| αντιγράφει ; στην οθόνη το πράτο μισό του τομέα αυτού
;
Το βιβλίο της Assembly για τον IBM PC και τους Συμβατούς
201
Λ ίσ τα 16-8. σ υ ν έ χ ε ι α PROC NEJ AL.0 CX.1 DX.0 ΒΧ,SECTOR
Οδηγός Α (αριθμός 0) Ανάγνωση 1 μόνο τομέα Ανάγνωση του τομέα 0 θέση αποθήκευσης του τομέα αυτού Ανάγνωση του τομέα Αποθήκευση σημαιών στη στοίβα από το DOS Καθορισμός σ χετικ ής διεύθυνσης 0 μέσα ..... ... ............ στον TOU8Q Εμφάνιση του ηρώτοο μισού Επιστροφή στο DOS
25h
20h ~ ENDP
READ_SECT0R
Αυτά είναι όλα όσα χρειαζόμαστε για να εμφανίσουμε τις πάνω και κάτω γραμμές στην οθόνη του τομέα. Κ ωδικοποιήστε και συνδέστε όλα αυτά τα αρχεία (θυμηθείτε να μεταφράσετε τα τρία αρχεία που αλλάξαμε), περάστε το αποτέλεσμα μέσα από το Exe2bin, και δοκιμάστε το. Η Εικόνα 16-3 δείχνει το αποτέλεσμα. Ας δούμε πώ ς δουλεύει η W RITE PATTERN. Ό π ω ς αναφέρθηκε, χρησιμοποιεί δυο καινούργιες εντολές. Η LODSB προέρχεται από το Load String Byte/Φ όρτω σ ε το byte αλφαριθμητικού, και είναι μια από τις εντο λές αλφαριθμητικώ ν: εντολές ειδικά σ χεδια σμένες που δουλεύουν με συμβολοσειρές χαρακτήρων. Δεν κάνουμε ακριβώ ς αυτό εδώ, αλλά ο 8088 δεν ενδιαφέρεται για το αν επεξεργαζόμαστε μια συμβολοσειρά χα ρ α κτήρων ή μόνον αριθμών, έτσι η LODSB εξυπηρετεί τους σκοπούς μας σε ικανοποιητι κά βαθμό. A>dlsk_ ΒΒ 01 02 83 Β4 05 86 87 08 Β9 ΒΑ 0Β BC 8D BE 0F ΒΒ 18 2Β 3Β 48 50
68 78 80 98 Αθ Β8
C8 D8 ΕΒ F8
ΕΒ Β2 88 D2 82 BF Α2 ΕΒ 88 Β1 ΒΒ Α1 6F F7 Βθ 89
21 70 00 79 8Ε 23 27 40 5F 0Β 03 11 01 26 Ε4 01
90 00 00 0Ε C5 7C 00 Ε8 BE 90 Cl 00 ΕΒ 8Β 83 ΕΒ
49 DB C4 89 8Ε Β9 BF ΒΒ 73 98 48 Β1 39 ΒΒ 74 55
42 82 5C ΙΕ D5 8Β 78 00 01 F3 F7 04 00 03 04 90
4D FD 08 ΙΕ BC ΒΒ 88 Εθ Β9 Α6 F1 D3 Ε8 DB FE 81
20 82 33 88 88 F3 Β8 86 ΒΒ 75 88 Ε8 64 5Α C4 86
28 88 ED 8C 7C Α4 23 ΒΒ ΒΒ 57 3Ε Εθ 88 ΕΒ 8Α ΙΕ
33 2Ε 89 80 Β8 C0 86 20 51 FC 1F 88 7C ΑΒ ΒΒ 88 98 F3 26 8Β 71 81 3Β ΒΒ 2Β F8 Ε9 CD CC 5Β ΒΒ 11
31 82 87 88 ΙΕ 8Ε 91 85 Α6 47 6Β FF 76 11 58 2Ε
ΒΒ ΒΒ 8Ε 88 36 2C ΑΒ 53 75 1C 75 36 8D Β9 FF 28
02 88 D8 16 C5 00 Α1 ΒΒ 62 99 82 ΙΕ Ε8 82 2Ε 88
02 00 33 22 36 Α0 16 01 83 8Β Βθ 0Β 26 88 6F C3
81 Βθ C9 00 70 18 00 Εθ C7 0Ε 14 C4 θθ D3 01 Α1
00 θθ ΘΑ Β1 θθ θθ D1 ΑΒ 15 ΘΒ 96 ΙΕ 52 Ε0 BE 18
ίΐέΙΒΜ 3.1....... • Ρ 1 · ....................
... - \ . 3 * L .X t 3 |. Π Λ ..Λ . ·4 ." .| Ί Ι1 |. .1(1.4. , . 4 . .
S’ o x . i l l W i . - T | . i h ‘uWii'e.0Y..
Α>
Εικόνα 16-3. Η Οθόνη μζ Κλειστά Πλαίσια.
..A«=t5>q.‘l l . |.a 6 . .- . ο . 1 9 .I d .+ = ν .SI.It « Ι ...+ Ζ ίθ -.{ ..·€
ς ζ . ι .ι - έ ϊ ι χ .o.J β .ίυ έ Μ·
202
Βελτίωση τη ς Ο θόνης του Τομέα
Η LODSB μετακινεί (φορτώνει) στον καταχω ρητή AL ένα byte από τη θέση μνήμης που δίνεται από τους DS:SI, ένα ζευγάρι καταχω ρητώ ν που δεν έχουμε ξαναχρησιμοποιήσει. Ό λ ο ι οι καταχω ρητές τμήμ ατος στο αρχείο .COM ρυθμίζονται στην αρχή του μοναδικού τμήματός μας, του CGROUP, έτσι ο DS είναι ήδη ρυθμισμένος για το τμήμα μας. Και πριν την εντολή LODSB, μετακινήσαμε τη σχετική διεύθυνση στον κα ταχω ρητή SI με την εντολή MOV SI.DX. Η εντολή LODSB είναι περίπου σαν τη MOV, αλλά πιο ισχυρή. Με μια εντολή LODSB, ο 8088 μετακινεί ένα byte στον καταχωρητή AL, και μετά είτε αυξάνει είτε μειώνει κ α τά ένα τον καταχω ρη-nf SI. Ο ταν αυξάνουμε κατά ένα τον καταχωρητή SI τότε αυτός δείχνει στο επόμενο byte της μνήμης, ενώ όταν τον μειώνουμε κατά ένα ο κα ταχω ρη τής δείχνει στο προηγούμενο byte της μνήμης. Η αύξηση αυτή κατά ένα είναι ακριβώ ς αυτό που θέλουμε να κάνουμε. Θέλουμε να ολοκληρώσουμε το σχήμα, byte πρ ο ς byte, αρχίζοντας από την αρχή, και αυτό ακρι βώς κάνει η εντολή LODSB, επειδή χρησιμοποιήσαμε την άλλη καινούργια εντολή, CLD (Clear Direction Flag/Μ η δέν ισ ε τη σημαία διεύθυνσης) που μηδενίζει τη σημαία διεύθυν σης. Αντίθετα, εάν δίναμε στη σημαία διεύθυνσης την τιμή 1, η εντολή LODSB θα μείω νε κατά ένα τον καταχωρητή SI. Θα χρησιμοποιήσουμε την εντολή LODSB και σε μερικά άλλα σημεία στο Dskpatch, πάντα με τη σημαία διεύθυνσης μηδενισμένη, για να αυξή σουμε κατά ένα. Ε κτός από τις LODSB και CLD, παρατηρήστε ότι χρησιμοποιήσαμε και τις εντολές PUSHF και PO PF για να αποθηκεύσουμε και να αποκαταστήσουμε τον καταχωρητή σημαίας. Το κάναμε αυτό για την περίπτωση που αργότερα θα αποφασίζαμε να χρησι μοποιήσουμε τη σημαία διεύθυνσης σε μια διαδικασία που καλεί τη WRITE PATTERN.
Προσθήκη Αριθμών στην Οθόνη Τελειώσαμε σχεδόν με το Μέρος II αυτού του βιβλίου. Θα δημιουργήσουμε ακόμα μια διαδικασία και μετά θα προχωρήσουμε στο Μέρος III και σε πιο αξιόλογα και εν διαφέροντα θέματα. Τώρα, προσέξτε ότι από την οθόνη μας λείπει μια σειρά αριθμών κατά μήκος της πρώ της γραμμής. Τέτοιοι αριθμοί — 00 01 02 03 κ.ο.κ . — θα μας επέτρεπαν να πα ρ α κολουθούμε προς τα κάτω τις στήλες για να βρούμε τη διεύθυνση οποιουδήποτε byte. Ετσι, θα γράψουμε μια διαδικασία που εμφανίζει αυτή τη σειρά αριθμών. Προσθέστε αυτή τη διαδικασία, τη WRITE TO P HEX NUMBERS, στο D IS P _ S E C _ A S M , α μέσως μετά την IN IT _ S E C _ D IS P :
Λίστα 16-9. Προσθέστε τη Δ ιαδικασία αυτή στο DISP-SEC.ASM
Το βιβλίο τη ς Assembly για τον IBM PC και τους Συμβατούς
203
Λίστα 16-9. συνέχεια Η διαδικασία αυτή εμφανίζει τους ο ύ ξο ντ ες αριθμούς (0 έως F) στην κορυφή της οθόνης μισού τομέα. Uses:
WRITE_CHAR_N_TIHES, WRITE_HEX, WRITE_CHAR WRITE_HEX_DIGIT. SEND_CRLF
WRITE_TOP_H£X_NUMBERS PUSH a PUSH DX DL,' ' a ,9 WRITE_CHAR_N_TIMES DH.DH HEX NUMBER LOOP:
;Εμφάνιση 16 κενών στην αριστερή πλευρά
;Αρχή με το 0
a .2 HRITE_CHAR_N_TIMES DL.DL WRITE_HEX_DIGIT DL DL.lOh HEX_DI6IT_L00P SEND_CRLF
WRITE_TOP_HEX_NUMBERS
Μετατρέψτε την INIT SEC DISP (κι αυτή στο DISP SEC.ASM) ω ς εξής, ώστε να καλεί τη W RITE Τ Ο Ρ _ Η Ε Χ NUMBERS πριν εμφανίσει το υπόλοιπο της οθόνης μισού τομέα:
Λίστα 16-10. Οι Α λ λα γές τη ς IN IT-SEC -D ISP στο DISP-SEC.ASM Uses:
WRITE_PATTERN, SEND_CRLF, DISP_HALF_SECTOR WRITE_TOP_HEX_NUMBERS T0P_LINE_PATTERN, B0TT0M_LINE_PATTERN
Reads: INIT_SEC_DISP PUSH
n
PROC DX
i M
NEAR
P
204
Βελτίωση της Ο θόνης του Τομέα
Λίστα 16-10. συνέχεια CALL CALL XOR CALL LEA CALL POP RET INIT_SEC_DISP
WRITE_PATTERN SEND_CRLF DX.DX DISP_HALF_SECTOR DX, B0TT0H_LINE_PATTERH WRITE_PATTERH DX
;Αρχή από την αρχή του τομέα
ENDP
Tcopa έχουμε μια πλήρη οθόνη μισού τομέα, όπω ς μπορείτε να δείτε στην Εικόνα 16-4. Υ πάρχουν ακόμα μερικές διαφορές μεταξύ αυτής της οθόνης και της τελικής έκδο σης. Θα αλλάξουμε τη W R IT E _ C H A R , έτσι ώστε να εμφανίζει όλους του 256 χα ρ α κτήρες που μπορεί να εμφανίσει ο IBM PC, και μετά θα καθαρίσουμε την οθόνη και θα την κεντράρουμε κατακόρυφα, χρησιμοποιώντας τις ρουτίνες του ROM BIOS του προσωπικού υπολογιστή IBM. Αυτό θα κάνουμε στη συνέχεια.
88 81 82 83 84 85 86 87 88 89 BA ΘΒ 8C BD BE BF βθ 1Β 28 38 4Β 58 68 78 88 98 Α8 Βθ C8 DB Ε0 F8
ΕΒ 82 88 D2 82 BF Α2 ΕΒ 88 Β1 88 Α1 6F F7 88 89
21 78 88 79 8Ε 23 27 48 SF 8Β 83 11 81 26 Ε4 81
98 49 88 DB 88 C4 8Ε 89 C5 8Ε 7C Β9 ΒΒ BF Ε8 88 BE 73 98 98 Cl 48 88 B1 Ε8 39 8Β 88 83 74 ΕΒ 55
42 82 SC IE D5 BB 78 88 81 F3 F7 84 88 83 84 90
4D 28 FD 82 88 33 IE 88 BC 88 88 F3 88 BB E8 86 B9 BB A6 75 FI 88 D3 EB E8 64 DB 5A FE C4 81 86
“ 1 28 33 2E 31 88 89 BB 82 ED BB CB 87 8C 86 2B BB 7C SI FC IE A4 IF 88 BE 23 7C AB 91 BB BB BB 85 88 9B F3 A6 57 26 8B 47 3E 71 01 68 EB 3B 88 FF BB 2B FB 76 EB E9 CD 11 8A CC SB 58 IE 8B 11 2E
88 82 62 88 88 BB 8E DB 33 B8 16 22 36 CS 36 2C BB AB AB A1 16 53 BB 81 75 62 83 1C 99 8B 75 82 BB 36 IE BB BD E8 26 B9 82 BB FF 2E 6F 2B BB C3
01 88 C9 0B 78 IB BB EB C7 8E 14 C4 BB D3 01 A1
BB BB BA B1 BB BB DI AB 15 BB 96 IE 52 EB BE IB
B123456789ABCDEF ίΐέΐΒΜ
3 . 1 .........
ρ Α « ............... ...- S .^ L .S + 3 ,
6* .·,χ .}ΙΙ> ί* !ίί..Τ . J . l ii'a b i» |.fefei5uwaie.OY.. i . J . k i : . 6 . .- . o .S 9 .id .+ = v .S I .R
.o.J ».iU fc................. [i.
Κικόνα 16-4. Μια Πλήρης Οθόνη Μισού Τομέα.
Περίληψη Φτιάξαμε πολλά πράγματα στο πρόγραμμά μας, το Dskpatch, προσθέτοντας καινούρ γιες διαδικασίες, αλλάζοντας παλιές, και μετακινώ ντας τμήματα από ένα αρχείο σε άλλο. Από δω και στο εξής, αν συμεί να χάσετε τον προσανατολισμό σας, ανατρέξτε
Το βιβλίο τη ς Assembly για τον IBM PC και τους Συμβατούς
205
στην πλήρη λίστα του Dskpatch στο Π αράρτημα Β. Η λίστα εκεί είναι η τελική έκδοση, αλλά κατά πάσα πιθανότητα θα δείτε αρκετές ομοιότητες που θα σας βοηθήσουν. Οι περισσότερες αλλαγές μας σ ’ αυτό το κεφάλαιο δεν βασίζονταν σε τεχνάσματα, αλλά μόνο σε σκληρή δουλειά. Μάθαμε ό μω ς δύο καινούργιες εντολές: τις LODSB και CLD. Η LODSB είναι μια από τις εντολές αλφαριθμητικών, που μας επιτρέπουν με μια εντολή να κάνουμε τη δουλειά αρκετώ ν. Χ ρησιμοποιήσαμε τη LODSB στη WRITE _PA T T E RN για να διαβάσουμε συνεχόμενα byte από τον πίνακα προτύπου σ χήματος, φορτώνοντας πάντα ένα καινούργιο byte στον καταχωρητή AL. Η CLD μηδενίζει τη σημαία διεύθυνσης, η οποία καθορίζει τη διεύθυνση της αύξησης. Κάθε εντολή LODSB που ακολουθεί φορτώνει το επόμενο byte απ ό τη μνήμη. Στο επόμενο μέρος αυτού του βιβλίου θα μάθουμε για τις ρουτίνες του ROM BIOS του IBM PC. Θα μας εξοικονομήσουν πολύ χρόνο.
Μ Ε ΡΟ Σ III
To R O M
BIOS
το υ IB M
PC
17
01 ΡΟΥΤΙΝΕΣ TOY ROM BIOS VIDEO ΙΟ, οι Ρουτίνες του ROM BIOS 210 Μετακίνηση του Δρομέα 215 Χρήση Μεταβλητών 217 Εκτύπωση Κεφαλίδας 220 Περίληψη 223
209
210
Οι Ρουτίνες του ROM BIOS
Λ ^ έ σ α στον προσωπικό υπολογιστή IBM υπάρχουν μερικά τσιπ, ή 1C (Integrated Cir cuits/Ο λο κλη ρω μένα Κ υκλώ μα τα), γνω στά σαν ROM (Read Only M emory/Μ ν ή μ η Μ ό νο Α νάγνω σης). Μια από αυτές τις ROM περιέχει μερικές ρουτίνες, που μοιάζουν πολύ με διαδικασίες, και παρέχουν όλες τις βασικές ρουτίνες για τη διεκπεραίωση εισόδου και εξόδου σε αρκετά διαφορετικά μέρη του IBM PC σας. Επειδή αυτή η ROM παρέχει ρουτίνες για την εκτέλεση εισόδου και εξόδου σε πολύ χαμηλό επίπεδο, αναφέρεται συ χνά σαν BIOS, από το Basic Input Output System (Βασικό Σύστημα Εισόδου Εξόδου). To DOS χρησιμοποιεί το ROM BIOS για τέτοιες δραστηριότητες όπω ς λ.χ. για να στέλ νει χαρακτήρες στην οθόνη και για να διαβάζει και να γράφει στο δίσκο, και μπορούμε να χρησιμοποιούμε ελεύθερα τις ρουτίνες του στα προγράμματά μας. Θα συγκεντρώσουμε την προσοχή μας στις ρουτίνες του BIOS που χρειαζόμαστε για το Dskpatch. Α νάμεσά τους είναι μία ομάδα για εμφάνιση στην οθόνη, οι οποίες περι λαμβάνουν μερικές λειτουργίες στις οποίες δεν θα μπορούσαμε αλλιώ ς να είχαμε πρό σβαση χωρίς να εργαστούμε απευθείας με το υλικό μέρος (hardware) — μια πολύ δύσκολη δουλειά.
VIDEO
ΙΟ, οι Ρουτίνες του ROM BIOS
Ο νομάζουμε τα στοιχεία του ROM BIOS ρουτίνες για να τις ξεχωρίζουμε από τις δια δικασίες. Χρησιμοποιούμε διαδικασίες με την εντολή CALL, ενώ καλούμε τις ρουτίνες με εντολές ΙΝΤ, όχι CALL. Θα χρησιμοποιήσουμε μια εντολή INT 10h, για παράδειγ μα, για να καλέσουμε τις ρουτίνες I/O για την οθόνη, όπω ς ακριβώ ς χρησιμοποιήσαμε την εντολή ΙΝΤ 21 h για να καλέσουμε ρουτίνες του DOS. Συγκεκριμένα, η ΙΝΤ 21 h καλεί τη ρουτίνα VIDEO ΙΟ του ROM BIOS. Ά λ λο ι αριθ μοί καλούν άλλες ρουτίνες, αλλά δεν θα δούμε καμμία από αυτές. Η VIDEO ΙΟ πα ρέχει όλες τις λειτουργίες που χρειαζόμαστε έξω από το DOS. (Πληροφοριακά ωστόσο, το DOS καλεί μια από τις άλλες ρουτίνες του ROM BIOS όταν ζητούμε ένα τομέα από το δίσκο.) Σ' αυτό το κεφάλαιο, θα χρησιμοποιήσουμε τις ρουτίνες του ROM BIOS για να προ σθέσουμε δυο νέες διαδικασίες στο Dskpatch: μια που θα καθαρίζει την οθόνη, και μια άλλη που θα μετακινεί το δρομέα σε οποιαδήποτε θέση της οθόνης επιλέγουμε. Και οι δυο είναι πολύ χρήσιμες λειτουργίες, αλλά καμία δεν είναι διαθέσιμη μέσω του DOS. Ά ρ α , θα χρησιμοποιήσουμε τις ρουτίνες του ROM BIOS για να κάνουμε αυτή τη δου λειά. Αργότερα, θα δούμε ακόμα πιο ενδιαφέροντα πράγματα που μπορούμε να κάνου με μ ’ αυτές τις ρουτίνες της ROM, αλλά α ς αρχίσουμε χρησιμοποιώντας την INT 10h για να καθαρίσουμε την οθόνη πριν εμφανίσουμε τον μισό τομέα μας. Η εντολή INT 10h είναι η είσοδός μας σε μερικές διαφορετικές λειτουργίες. Θυμηθεί τε ότι, όταν χρησιμοποιήσαμε την εντολή του DOS INT 21h, επιλέξαμε μια συγκεκριμέ νη λειτουργία τοποθετώντας τον αριθμό της στον καταχωρητή ΑΗ. Επιλέγουμε μια λειτουργία του V ID E O _ IO με τον ίδιο ακριβώ ς τρόπο: τοποθετώ ντας τον κατάλληλο αριθμό λειτουργίας στον καταχωρητή ΑΗ (μια πλήρης λίστα αυτών των λειτουργιών δίνεται στον Π ίνακα 17-1).
Το βιβλίο της Assembly για τον IBM PC και τους Συμβατούς
211
Π ίνακας 17-1. Λειτουργίες INT 10h (ΑΗ) = 0
Καθορισμός κατάστασης οθόνης. Ο καταχω ρητής AL περιέχει τον αριθμό κα τάστασης. ΚΑΤΑΣΤΑΣΗ ΚΕΙΜΕΝΟΥ (AL) = 0 40 (A L)= 1 40 (AL) = 2 80 (AL) = 3 80 (AL) = 7 80
επί επί επί επί επί
25, 25, 25, 25, 25,
κατάσταση ασπρόμαυρη έγχρωμη ασπρόμαυρη έγχρωμη μονόχρω μος προσαρμογέας οθόνης
ΚΑΤΑΣΤΑΣΗ ΓΡΑΦΙΚΩΝ (AL) = 4 320 επί 200, έγχρωμη (AL) = 5 320 επί 200, ασπρόμαυρη (AL) = 6 640 επί 200, ασπρόμαυρη
(ΑΗ)= 1
Καθορισμός μεγέθους του δρομέα. (CH)
(CL)
Α ρχική γραμμή σάρωσης του δρομέα. Η πρώτη άνω γραμμή είναι η 0 τόσο για τις μονόχρωμες όσο και για τις έγχρω μες οθόνες γραφικώ ν, ενώ η κάτω γραμμή εί ναι η 7 για τον προσαρμογέα έγχρω μων γραφικώ ν και η 13 για το μονόχρωμο προσαρμογέα. Επιτρεπτή περιοχή τιμών: 0 έως 31. Τελευταία γραμμή σάρωσης του δρομέα.
Η ρύθμιση "ανοικτό" (on) για τον προσαρμογέα εγχρώ μων γραφι κών είναι CH = 6 και CL = 7. Γ ια τη μονόχρωμη οθόνη: CH = 11 και C L = 12.
(ΑΗ) = 2
Καθορισμός της θέσης του δρομέα. (DH.DL)
Σειρά, στήλη της νέας θέσης του δρομέα. Η πάνω αρι στερή γωνία είναι η (0,0).
(ΒΗ)
Α ριθμός σελίδας. Αυτός είναι ο αριθμός της σελίδας οθόνης. Ο προσαρμογέας έγχρωμων γραφικών έχει χώ ρο για αρκετές σελίδες οθόνης, αλλά τα περισσότερα προγράμματα χρησιμοποιούν τη σελίδα 0.
212
Οι Ρουτίνες του ROM BIOS
Π ίνακα ς 17-1. συνέχεια (ΑΗ) = 3
Α νάγνωση της θέσης του δρομέα. (ΒΗ) Α ριθμός σελίδας On exit (DH.DL) Σειρά, στήλη του δρομέα (CH.CL) Μ έγεθος του δρομέα
(ΑΗ) = 4
Ανάγνωση θέσης φωτογραφίδας (βλέπε και αντίστοιχο Εγχειρίδιο).
(ΑΗ) = 5
Ε πιλογή ενεργής σελίδας οθόνης. (AL)
(ΑΗ) = 6
Κύλιση προς τα άνω. (AL)
(CH.CL) (DH.DL) (ΒΗ)
(ΑΗ) = 7
Ν έος αριθμός σ ελίδας (από 0 έως 7 για καταστάσεις 0 και 1, από 0 έως 3 για κα ταστάσεις 2 και 3)
Α ριθμός γραμμώ ν για καθάρισμα στο κάτω μέρος του παραθύρου. Η κανονική κύλιση καθαρίζει μια γραμ μή. Ρυθμίστε στο μηδέν για να καθαρίσετε ολόκληρο το παράθυρο. Σειρά, στήλη της άνω, αριστερής γω νίας του πα ραθύρου Σειρά, στήλη της κάτω , δεξιάς γ ω νίας του παραθύρου Ιδιότητα οθόνης που θα χρησιμοποιηθεί για τις κενές γραμμές
Κύλιση προς τα κάτω. Το ίδιο ό πω ς και η κύλιση πρ ος τα πάνω (λειτουργία 6), αλλά οι γραμμές αφήνονται κενές στο πάνω μέρος του παραθύρου και όχι στο κάτω μέρος
(ΑΗ) = 8
Ανάγνωση ιδιότητας και χαρακτήρα στην θέση του δρομέα. (ΒΗ)
Σελίδα οθόνης (μόνο καταστάσεις κειμένου)
Το βιβλίο της Assembly για τον IBM PC και τους Συμβατούς
213
Πίνακας 17-1. συνέχεια (ΑΗ) = 8
(AL) (ΑΗ)
(ΑΗ) = 9
Εμφάνιση ιδιότητας καα χαρακτήρα στη θέση του δρομέα. (ΒΗ) (CX) (AL) (BL)
(ΑΗ) = 10
Χ αρακτή ρας που διαβάστηκε Ιδιότητα του χαρακτήρα που διαβάστηκε (μόνο κα τα στάσεις κειμένου)
Σελίδα οθόνης (μόνο κα ταστάσεις κειμένου) Α ριθμός εμφανίσεων χαρακτήρα και ιδιότητας οθόνης Χ αρακτήρας πρ ος εμφάνιση Ιδιότητα πρ ο ς εμφάνιση
Εμφάνιση χαρακτήρα στη θέση του δρομέα. (ΒΗ) (CX) (AL)
Σελίδα οθόνης Αριθμός εμφανίσεων του χαρακτήρα Χ αρακτήρας προς εμφάνιση
(ΑΗ) =11 έως 13
Διάφορες λειτουργίες γραφικών.
(ΑΗ)= 14
Τηλετυπική εμφάνιση. Εκτύπω ση ενός χαρακτήρα στην οθόνη και μετακίνηση του δρομέα στην επόμενη θέση. (AL) (BL) (ΒΗ)
(ΑΗ)= 15
Χ αρακτήρας προς εμφάνιση Χ ρώμα του χαρ ακτήρα (μόνο σε κατάσταση γραφικών) Σελίδα οθόνης (κατάσταση κειμένου)
Επιστροφή τρέχουσας κατάστασης οθόνης. (AL) (ΑΗ) (ΒΗ)
Τρέχουσα ρύθμιση κα τάστασης οθόνης Αριθμός χαρακτήρω ν ανά γραμμή Ενεργές σελίδες οθόνης
Θα χρησιμοποιήσουμε την INT 10h με αριθμό λειτουργίας 6, ΚΥΛΙΣΗ ΕΝΕΡΓΗ Σ ΣΕ ΛΙΔΑΣ Π ΡΟ Σ ΤΑ ΑΝΩ, για να καθαρίσουμε την οθόνη. Δεν θέλουμε στην πρα γμ ατι κότητα να κυλίσουμε την οθόνη, αλλά αυτή η λειτουργία είναι ίδια με τη συνάρτηση καθαρισμού οθόνης. Να η διαδικασία, εισάγετέ την στο αρχείο CURSOR.ASM:
214
Οι Ρουτίνες του ROM BIOS
Λίστα 17-1. Προσθέστε τη Δ ιαδικασία αυτή στο CURSOR.ASM PUBLIC
CLEAR_SCREEN
Η διοδικααία αυτή καθαρίζει όλη την οθόνη CLEAR SCREEN PUSH PUSH PUSH PUSH XOR XOR NOV NOV NOV NOV INT POP POP POP POP RET CLEAR SCREEN
PROC AX BX a DX AL.AL CX.CX DH.24 DL.79 BH.7 AH. 6 lOh DX a BX AX
; Καθαρισμός όλου του παραθύρου ;Επάνϋ αριστερή γονία ατο (0,0) ;Η κότυ-κότυ γραμμή της οθόνης είναι η 24 ;Το δεξιό όριο βρίσκεται στη στήλη 79 ;Κανονικές ιδιότητες χρυμότυν για τα κενά ;Κλήση της λειτουργίας SCR0LL-UP ; Καθαρισμός του παραθύρου
ENDP
Φαίνεται ότι η INT 10h με αριθμό λειτουργίας 6 χρειάζεται πολλές πληροφορίες, αν και το μόνο που θέλουμε να κάνουμε είναι να καθαρίσουμε την οθόνη. Αυτή η λειτουρ γία είναι μάλλον ισχυρή: Μπορεί στην πραγματικότητα να καθαρίσει οποιαδήποτε πα ραλληλόγραμμη περιοχή της οθόνης — παράθυρο — όπω ς ονομάζεται. Πρέπει να καθορίσουμε σαν παράθυρο ολόκληρη την οθόνη θέτοντας την πρώτη και τελευταία γραμ μή στο 0 και 24 αντίστοιχα, και θέτοντας τις στήλες στα 0 και 79. Οι ρουτίνες που χρη σιμοποιούμε εδώ μπορούν επίσης να καθαρίσουν την οθόνη με λευκό χρώμα (για μαύρους χαρακτήρες), ή με μαύρο χρώμα (για λευκούς χαρακτήρες). Θέλουμε το τελευταίο, και αυτό καθορίζεται με την εντολή MOV ΒΗ,7. Κατόπιν, θέτοντας τον AL ίσο με 0, τον αριθμό γραμμώ ν προς κύλιση, λέει σ' αυτή τη ρουτίνα να καθαρίσει το παράθυρο, αντί να το κυλίσει. Τώρα πρέπει να τροποποιήσουμε τη δοκιμαστική μας διαδικασία, READ SECTOR, για να καλεί την CLEAR SCREEN ακριβώ ς πριν αρχίσει να εμφανίζει την οθόνη του τομέα. Δεν βάλαμε αυτή την εντολή CALL στην ΙΝΙΤ SEC DISP, επειδή θα θελήσουμε να χρησιμοποιήσουμε την IN IT _ S E C _ D IS P για να ξαναεμφανίζει μόνο την ο θόνη μισού τομέα, χωρίς να επηρεάζει το υπόλοιπο της οθόνης. Για να τροποποιήσετε τη READ SECTOR, προσθέστε μια δήλωση EXTRN για την CLEAR SCREEN και βάλτε την CALL στην CLEAR SCREEN. Κάντε τις ακόλου θες αλλαγές στο αρχείο DISK._IO.ASM :
Το βιβλίο της Assembly για τον IBM PC και τους Συμβατούς
2 /5
Λίστα 17-2. Ο ι Α λ λ α γ έ ς τ η ς R E A D -S E C T O R σ το D IS K -IO .A S M . EXTRN
ΙΝΙΤ SEC DISP: NEAR,
CLEAR_SCREEN: NEAR
; Η διαδικασία αυτή διαβάζει τον πρϋτο τομέα του δίσκου Α και αντιγράφει ; στην οθόνη το πράτο μισό του τομέα αυτού READ SECTOR MOV MOV MOV LEA INT POPF XOR
PROC NEAR AL.O CX.l DX.O BX.SECTOR 25h
CALL CALL INT READ SECTOR
CLEAR SCREEN INIT SEC DISP 20h ENDP
DX.DX
;
.Οδηγός A (αριθμός 0) ;Ανάγνυση 1 μόνο τομέα ;Ανάγνυση του τομέα 0 ;θέση αποθήκευσης του τομέα αυτού ;Ανάγνωση του τομέα ;Αποθήκευση σημαιών στη στοίβα από το [ ;Καθορισμός σχετικής διεύθυνσης 0 μέσα ;στον τομέα ; Εμφάνιση του πρώτου μισού ; Επιστροφή στο DOS
Ακριβώς πριν εκτελέσετε την καινούργια έκδοση του Disk ίο, προσέξτε πού βρίσκεται ο δρομέας. Μ ετά, τρέξτε το Disk ίο. Η οθόνη θα καθαρίσει, και το Disk ίο θα αρχί σει την εκτύπωση της οθόνης μισού τομέα από οπουδήποτε έτυχε να βρίσκεται ο δρο μέας πριν εκτελέσετε το πρόγραμμα — πιθανόν στο κάτω μέρος της οθόνης. Αν και καθαρίσαμε την οθόνη, δεν αναφέραμε τίποτε για τη μετακίνηση του δρομέα πάλι στο άνω μέρος. Στην BASIC, η διαταγή CLS καθαρίζει την οθόνη σε δύο βήματα: Καθαρίζει την οθόνη, έπειτα μετακινεί το δρομέα στο άνω μέρος της. Η διαδικασία μας δεν το κάνει αυτό. Θα πρέπει να μετακινήσουμε το δρομέα μόνοι μας.
Μετακίνηση του Δρομέα Η ΙΝΤ 1Oh με αριθμό λειτουργίας 2 ρυθμίζει τη θέση του δρομέα με τον ίδιο περίπου τρόπο που το κάνει η εντολή LOCATE της BASIC. Μ πορούμε να χρησιμοποιήσουμε τη GOTO ΧΥ για να μετακινήσουμε το δρομέα οπουδήποτε στην οθόνη (όπω ς λ.χ. στο πάνω μέρος μετά από ένα καθάρισμα), αλλά δεν θα το κάνουμε. Εισάγετε αυτή τη διαδικασία στο αρχείο CURSOR.ASM: Λ ίσ τα 17-3. Π ρ ο σ θ έσ τε τη Δ ια δ ικ α σ ία Α υ τή σ το C U R S O R .A S M PUBLIC
G0T0_XY
Η διαδικασία αυτή μετακινεί το δρομέα DH DL
Γραμμή (Υ) Στήλη (X)
PUSH PUSH
PROC ΑΧ ΒΧ
60Τ0_ΧΥ
NEAR
216
Οι Ρουτίνες του ROM BIOS
Λ ίστα 17-3. συνέχεια MOV MOV INT POP POP
;Εμφάνιση της σελίδας 0 ;Κλήση της SET CURSOR POSITION
ΒΗ.ο ΑΗ.2 10h ΒΧ ΑΧ
60Τ0_ΧΥ
Θα χρησιμοποιήσουμε την GOTO ΧΥ σε μια αναθεωρημένη έκδοση της ΙΝΙΤ SEC DISP, για να μετακινήσουμε το δρομέα στη δεύτερη γραμμή λίγο πριν εμφανί σουμε την οθόνη μισού τομέα. Να οι τροποποιήσεις στην ΙΝΙΤ S E C _ D IS P του DISP SEC.ASM:
Λ ίστα 17-4. Οι Α λ λα γές της INIT-SEC-DISP στο DISP-SEC.ASM PUBLIC INIT_SEC_DISP EXTRN WRITE_PATTERN:NEAR. SEND_CRLF: NEAR EXTRN G0T0_XY:NEAR ; Η διαδικασία αυτή ετοιμάζει την απεικόνιση του μισού τομέα Uses:
;
WRITEPATTERN, SEND_CRLF, DISP_HALF_SECTOR
Reads: INIT_SEC_DISP
PROC
NEAR
Αν τη δοκιμάσετε τώρα, θα δείτε ότι η οθόνη του μισού τομέα είναι ωραία κεντραρισμένη. Ο πω ς μπορείτε να δείτε τώρα, είναι εύκολο να δουλεύουμε με την οθόνη όταν έχουμε τις ρουτίνες του ROM BIOS. Στο επόμενο κεφάλαιο, θα χρησιμοποιήσουμε μια άλλη ρουτίνα του ROM BIOS για να βελτιώσουμε τη W R IT E _C H A R , έτσι ώστε να εκτυπώ νει οποιονδήποτε χαρακτήρα στην οθόνη. Α λλά πριν συνεχίσουμε, α ς κάνουμε μερικές άλλες αλλαγές στο πρόγραμμά μας, και μετά να τελειώσουμε με μια διαδικασία που ονομάζεται WRITE HEADER, η οποία θα εκτυπώνει μια γραμμή κα τάστασης στο πά νω μέρος της οθόνης, που θα δείχνει τον τρέχοντα οδηγό δίσκου και τον αριθμό τομέα.
Τ ο βιβλίο της Assembly για τον IBM PC και τους Συμβατούς
217
Χρήση Μεταβλητών Εχουμε πολλά να αλλάξουμε πριν δημιουργήσουμε τη W RITE HEADER. Ο πω ς είναι τώρα, πολλές από τις διαδικασίες μας περιέχουν αριθμούς α π ’ αυθείας συνδεδεμένους με το hardware. Η READ SECTOR, για παράδειγμα, διαβάζει τον τομέα 0 στον οδηγό Α. Θέλουμε να βάλουμε τους αριθμούς του οδηγού δίσκου και του τομέα σε με ταβλητές μνήμης, έτσι ώστε να μπορούν να τους διαβάσουν περισσότερες διαδικασίες. Θα χρειαστεί να αλλάξουμε αυτές τις διαδικασίες έτσι ώστε να χρησιμοποιούν μετα βλητές μνήμης, αλλά α ς αρχίσουμε βάζοντας όλες τις μεταβλητές μνήμης σε ένα αρ χείο, το DSKPATCH.ASM, για να κάνουμε τη δουλειά μας απλούστερη. To Dskpatch.asm θα είναι το πρώ το αρχείο στο πρόγραμμα Dskpatch, έτσι οι μεταβλητές μνήμης θα μπο ρούν να βρεθούν εύκολα εκεί. Να το DSKPATCH.ASM, ολοκληρωμένο με μια εκτενή λίστα μεταβλητών μνήμης:
Λίστα 17-5. Το Νέο Αρχείο DSKPATCH.ASM CGROUP
GROUP ASSUME
C00E_SE6, DATA_SEG CS:CGROUP, DS:CGROUP
C00E_SE6SEGMENT PUBLIC ORG 100b EXTRN EXTRN DISK_PATCH CALL CALL CALL INT DISK_PATCH
CLEAR_SCREEN:NEAR, READ_SECTOR:NEAR INIT_SEC_DISP:NEAR PROC NEAR CLEARSCREEN READ_SECTOR INIT_SEC_DISP 2 Oh ENDP
COOE_SE6 ENDS DATA_SEGSEGMENT PUBLIC PUBLIC SECT0R_0FFSET SECTOROFFSET e iv o i η σχετική διεύθυνση της οθόνης μισού τομέα μέσα στον πλήρη τομέα. Πρέπει να ε ίν α ι πολλαπλάσιο του 16, και όχι μεγαλύτερο από το 256 SECTOR_OFFSET
DU
0
PUBLIC CURRENT_SECTOR_NO, DISK_DRIVE_NO CURRENTSECTORNO DU 0 DISK_DRIVE_NO DB 0 PUBLIC PUBLIC
;Αρχικό τομέας 0 :Αρχικά οδηγός A:
LINES_BEFORE_SECTOR, HEADER_LINE_NO HEADER_PART_1, HEADER_PART_2
218
Οι Ρουτίνες του ROM BIOS
Λ ί σ τ α 17-5. σ υ ν έ χ ε ια LINES_BEFORE_SECTOR Είναι ο αριθμός γραμμών ατο άνι» μέρος της οθόνης, πριν από την απεικόνιση του μισού τομέα LINES_BEFORE_SECTOR HEADER_LINE_NO HEA0ER_PART_1 HEADER_PART_2 PUBLIC
SECTOR
; Ολόκληρος ο τομέος (μέχρι 8192 bytes) αποθηκεύ; βται στο τμήμα αυτό της μνήμης. SECTOR
06
8192 DUP (0)
DATA_SEGENDS END
DISK_PATCH
Η κύρια διαδικασία, η DISK PA TCH , καλεί τρεις άλλες διαδικασίες. Τις έχουμε δει όλες πριν. Σύντομα θα ξαναγράψουμε τόσο τη READ SECTOR όσο και την ΙΝΙΤ _ S E C _ D IS P , έτσι ώστε να χρησιμοποιούν τις μεταβλητές που μόλις βάλαμε στο τμή μα δεδομένων. Πριν μπορέσουμε να χρησιμοποιήσουμε το Dskpatch, πρέπει να τροποποιήσουμε τη Disp sec, αντικαθιστώ ντας τον ορισμό της SECTOR με μια EXTRN. Πρέπει επίσης να αλλάξουμε τη Disk io, τροποποιώντας τη R EA D _SECTO R σε μια συνηθισμένη δια δικασία που μπορούμε να καλέσουμε από το Dskpatch. Α ς πάρουμε τη SECTOR πρώτα. Αφού την τοποθετήσαμε στο DSKPATCH.ASM σαν μια μεταβλητή μνήμης, πρέπει να αλλάξουμε τον ορισμό της SECTOR στη Disp secμε μια δήλωση EXTRN. Κάντε αυτές τις αλλαγές στο D ISP_SEC .A SM : Λ ίσ τα 17-6. Ο ι Α λ λ α γ έ ς σ το D IS P -S E C .A S M DATA_SEGSEGMENT Wm* PUBLIC SECTOR DB
PUBLIC SECTOR: BYTE SECTOR 512 DUP(O)
T0P_L I NE_PATTERN LABEL BYTE DB ' '.7 DB UPPER_LEFT,1
Το βιβλίο της Assembly για τον IBM PC και τους Συμβατούς
219
Ας ξαναγράψουμε το αρχείο DISK ΙΟ.ASM έτσι ώ στε να περιέχει μόνο διαδικασίες, και η R E A D _SE C T O R να χρησιμοποιεί μεταβλητές μνήμης (όχι α π ’ ευθείας αριθμούς) για τους αριθμούς τομέα και οδηγού δίσκου. Να η καινούργια έκδοση του DISK ΙΟ .ASM: Λ ίσ τα 17-7. Ο ι Α λ λ α γ έ ς σ το D IS K -IO .A S M CGROUP
GROUP ASSUME
C0DE_SEG. DATA_SE6 CS:CGROUP, DS:CGROUP
C0DE_SEGSEGMENT PUBLIC
ORG
lOOh
PUBLIC READ SECTOR BATA_SEGSEGMENT PUBLIC ^ EXTRN EXTRN
DI SK_DRIVE_N0:BYTE CURRENT SECTORJKktfORD ENDS
0ATA_SE6
EXTRN
INIT_SEC_DISP:NEAR. CLEAR_SCREEH:NEAR
Η διαδικασία αυτή μεταφέρει έναν τομέα (512 byte) στο SECTOR. Reads: Writes:
CURRENT_SECTOR_NO, DISK_DRIVE_NO SECTOR PROC AX BX
READ SECTOR PUSH PUSH PUSH PUSH MOV MOV MOV LEA INT POPF
a DX AL.DISK DRIVE NO CX.l DX.CURRENT SECTOR NO BX.SECTOR
25h
XOR CALL CALL INT POP POP POP
DX.DX CLEAR SCREEN IN IT SEC DISP 20h ■
■ B ·
RET READ_SECTOR
ENDP
C0DE_SEG
ENDS
DATA SEG EXTRN DATA SEG END
NEAR
SEGMENT PUBLIC SECTOR:BYTE ENDS
;Apιθμός οδηγού ;Ανάγνυση ενός μόνο τομέα ;Αριθμός λογικού τομέα ;θέση αποθήκευσης τομέα ;Ανάγνοση τομέα ;Απόρριψη τον σημαιών που το DOS ;αποθήκευσε στη στοίβα
-.Σχετική διεύθυνση 0, μέσα στον τομέα ; Εμφάνιση του προτού μισού
220
Οι Ρουτίνες του ROM BIOS
Αυτή η καινούργια έκδοση του Disk io χρησιμοποιεί τις μεταβλητές μνήμης DISK DRIVE NO και CURRENT SECTOR NO σαν αριθμούς οδηγού δίσκου και το μέα, αντίστοιχα, για τον τομέα που θα διαβαστεί. Αφού αυτές οι μεταβλητές είναι ήδη ορισμένες στο DSKPATCH.ASM, δεν θα χρειαστεί να αλλάξουμε τη Disk io όταν θα αρχίσουμε να διαβάζουμε διαφορετικούς τομείς από άλλους οδηγούς δίσκω ν. Αν χρησιμοποιείτε το πρόγραμμα Make για να ξαναφτιάξετε το DSKPATCH.COM, θα χρειαστεί να κάνετε μερικές προσθήκες στο αρχείο Make που ονομάζεται Dskpatch: Λ ίσ τα 17-8. Η Ν έ α Έ κ δ ο σ η του D S K P A T C H
d is k _ io .o b j: d isk _ io .i masm d isk _ io ; d isp _ se c .o b j: d isp_sec.asm masm d i s p s e c ; v id e o io .o b j :
vid eo _ io .a sm
c u r so r.o b j: cursor.asm masm cursor;
Αν δεν χρησιμοποιείτε το Make, φροντίστε να ξανακω δικοποιήσετε και τα τρία αρ χεία που έχουν αλλαχτεί (τα Dskpatch, Disk io, και Disp sec), και να συνδέσετε και τα πέντε αρχεία, με το Dskpatch πρώ το στη λίστα: LINK DSKPATCH D ISKJO DISP_SEC VIDE0_I0 CURSOR; EXE2BIN DSKPATCH DSKPATCH.COH
Κάναμε αρκετές αλλαγές, γι αυτό δοκιμάστε το Dskpatch και σιγουρευτείτε ότι δου λεύει σωστά πριν προχωρήσετε.
Εκτύπωση Κεφαλίδας Τώρα που μετατρέψαμε τους αριθμούς σε άμεσες αναφορές σε μεταβλητές μνήμης, μπορούμε να γράψουμε τη διαδικασία W RITE HEADER έτσι ώ στε να εμφανίζει μια γραμμή κα τάστασης, ή κεφαλίδα (header), στο πάνω μέρος της οθόνης. Η κεφαλίδα μας θα είναι ω ς εξής:
Το βιβλίο τη ς Assembly για τον IBM PC και τους Συμβατούς
Disk A
221
S ecto r 0
Η WRITE HEADER θα χρησιμοποιεί τη WRITE DECIMAL για να εκτυπώ νει τον τρέχοντα αριθμό τομέα σε δεκαδική μορφή. ·Θα εκτυπώ νει επίσης δύο συμβολοσειρές χαρακτήρων, τις Disk και Sector (καθεμιά ακολουθούμενη από ένα κενό διάστημα), και ένα γράμμα οδηγού δίσκου, όπω ς π.χ. ένα Α. Θα βάλουμε τη διαδικασία στο αρχείο VIDEO IO.ASM. Για να αρχίσουμε, αφού θα κάνουμε αναφορά στο τμήμα δεδομένων (DATA SEG), αλλάξτε την πρώτη γραμμή (την εντολή GROUP) στο V ID E O _IO .A SM σε: CGROUP
GROUP
COOESEG. DATASEG
Βάλτε την ακόλουθη διαδικασία στο VIDEO
IO.ASM:
Αίσια 17-9. Προσθέστε τη Διαδικασία Αυτή στο VIDEO-IO.ASM PUBLIC WRITEJCADER DATA_SEGSEGMENT PUBLIC EXTRN HEADER_LINE_NO:BYTE EXTRN HEADER_PART_1: BYTE EXTRN HEADER_PART_2:BYTE EXTRN DISK_DRIVE_NO:BYTE EXTRN CURRENT_SECTOR_NO:WORD DATASE6 ENDS EXTRN GOTO_XY:NEAR Η διαδικασία αυτή γράφει την κεφαλίδα με τον αριθμό οδηγού και τομέα Uses: Reads:
60Τ0_ΧΥ, WRITESTRING. WRITECHAR, URITE_DECIHAL HEADERLINE_NO. HEADER_PART_1, HEADER_PART_2 DIStCDRIVENO. CURRENT_SECTOR_NO
WRITE HEADER PUSH XOR
PROC DX DL.DL
MOV CALL LEA CALL NOV ADD CALL LEA CALL NOV CALL POP RET WRITE HEADER
DH,HEADER LINE NO GOTO XY DX.HEADER PART 1 WRITE STRING DL.DISK DRIVE NO DL.'A ’ WRITE CHAR DX,HEADER PART 2 WRITE STRING DX,CURRENT SECTOR NO WRITE DECIMAL DX ENDP
NEAR ; Μετακίνηση του δρομέα οτον αριθμό ;γραμμής της κεφαλίδας
;Εμφάνιση οδηγόν A, Β, . . .
222
Οι Ρουτίνες του ROM BIOS
Η διαδικασία W RITE STRING δεν υπάρχει ακόμα. Ό π ω ς μπορείτε να δείτε, σ χε διάζουμε να τη χρησιμοποιήσουμε για να εμφανίζουμε μια συμβολοσειρά χαρακτήρω ν στην οθόνη. Οι δυο συμβολοσειρές, HEADER PART 1 και HEADER PART 2, είναι ήδη ορισμένες στο DSKPATCH.ASM. Η W RITE STRING θα χρησιμοποιεί τη DS:DX σαν τη διεύθυνση της συμβολοσειράς. Δ ιαλέξαμε να δώσουμε τη δική μας διαδικασία εξόδου αλφαριθμητικού, έτσι ώστε οι συμβολοσειρές μας να μπορούν να περιέχουν οποιοδήποτε χαρακτήρα, συμπεριλαμ βανομένου του $, τον οποίο δεν μπορούσαμε να εμφανίσουμε με τη λειτουργία 9 του DOS. Εκεί που το DOS χρησιμοποιεί ένα $ για να σημειώσει το τέλος ενός αλφαριθμητι κού, θα χρησιμοποιήσουμε ένα δεκαεξαδικό 0. Να η διαδικασία. Τοποθετήστε τη στο VIDEO ΙΟ. ASM: Λ ίσ τα 17-10. Π ρ ο σ θ έσ τε τη Δ ια δ ικ α σ ία Α υ τή σ το V ID E O -IO .A S M PUBLIC
WRITE_STRIN6
Η δ ιοδ ικοσ ία αυτή εμφανίζει ένα αλφαριθμητικό χαρακτήραν ατην οθόνη. Το αλφαριθμητικό πρέπει να τελειώ νει με DB 0 DS:DX
Διεύθυνση αλφαριθμητικού
; Uses:
WRITECHAR
WRITE STRING PUSH PUSH PUSH PUSHF CLO MOV
PROC AX DX SI
STRING LOOP: LODSB OR JZ MOV CALL JMP END OF STRING: POPF POP POP POP RET WRITE STRING
NEAR
SI.DX
AL.AL END OF STRING DL.AL WRITE CHAR STRING_LOOP
;Αποθήκευση σημαίας διεύθυνσης ;Καθορισμός διεύθυνσης προσαύξησης ;Αποθήκευση διεύθυνσης στον SI ;γ ια τη L0DSB ;Αποθήκευση ενό ς χαρακτήρα οτον AL ; Βρέθηκε το 0; ;Ναι, τελειώσαμε με το αλφαριθμητι» ; ' 0 χ ι , εμφάνιση του χαρακτήρα
;Αποκοτάοταοη σημαίας διεύθυνσης SI DX AX ENDP
Ό π ω ς είναι τώρα, η WRITE STRING θα εμφανίζει τους χαρακτήρες που έχουν ASCII κω δικούς κάτω από 32 (ο χαρακ τήρας κενού διαστήματος) σαν τελείες (.), επειδή δεν έχουμε μια έκδοση της W RITE CHAR που να εμφανίζει οποιονδήποτε χαρακτήρα. Θα φροντίσουμε γι αυτή τη λεπτομέρεια στο επόμενο κεφάλαιο. Μετά από όλη την εργασία μας σ ’ αυτό το κεφάλαιο, α ς βάλουμε το σιρόπι στο κέϊκ.
Το βιβλίο της Assembly για τον IBM PC και τους Συμβατούς
223
Αλλάξτε την DISK PATCH στο DSKPATCH.ASM ώστε να περιλαμβάνει την CALL στη WRITE HEADER: Λ ίσ τα 17-11. Ο ι Α λ λ α γ έ ς τ η ς D IS K -P A T C H σ το D S K P A T C H .A S M EXTRN
CLEAR SCREEN:NEAR, READ SECTOR:NEAR
« « , , r
CALL
CLEARSCREEN
is
h up INIT_SEC_DISP
CALL INT DISK_PATCH
20h ENDP
To Dskpatch πρέπει τώρα να δίνει μια οθόνη όπω ς αυτή στην Εικόνα 17-1.
Disk A
S e c to r Β 00 81 02 83 84 85 86 87 88 89 ΘΑ 8Β 0C 8D ΘΕ 8F
βθ 1θ 20 3Θ 4Β 50 68 70 80 90 Α0 Β0 C0 DB £0 F0
ΕΒ 02 00 D2 02 BF Α2 Ε0 80 Β1 00 Α1 6F F7 80 89
21 78 88 79 8Ε 23 27 40 5F ΒΒ 03 11 01 26 Ε4 01
98 88 88 BE C5 7C 88 Εθ BE 98 Cl 88 ΕΒ ΒΒ 83 ΕΒ
49 D8 C4 89 8Ε Β9 BF 88 73 98 48 Β1 39 88 74 55
42 82 5C ΙΕ D5 0Β 78 88 81 F3 F7 84 08 83 84 98
4D FD 88 ΙΕ BC 88 88 Ε8 Β9 Α6 F1 D3 Ε8 D8 FE 81
28 82 33 88 88 F3 Ββ 86 ΘΒ 75 88 Ε8 64 5Α C4 86
28 88 ED 8C 7C Α4 23 88 88 57 3Ε Ε8 88 ΕΒ 8Α ΙΕ
33 89 ΒΒ 86 51 1F 7C ΒΒ 98 26 71 3Β 2Β Ε9 CC 88
2Ε 88 CB 28 FC 8Β ΑΒ 88 F3 8Β 81 88 F8 CD 5Β 11
31 82 87 88 ΙΕ ΘΕ 91 05 Α6 47 60 FF 76 11 58 2Ε
” 1 88 02 88 θθ 8Ε D8 68 16 36 C5 2C 00 ΑΒ Α1 53 Β8 75 62 1C 99 75 82 36 ΙΕ 8D ΕΒ Β9 82 FF 2Ε 20 88
82 88 33 22 36 ΑΒ 16 81 83 ΒΒ Β8 θθ 26 θθ 6F C3
Θ1 θθ C9 θθ 78 18 Βθ Ε8 C7 ΘΕ 14 C4 00 D3 81 Α1
08 88 8Α Β1 θθ θθ D1 ΑΒ 15 ΒΒ 96 ΙΕ 52 Εθ BE 18
8123456769ABCDEF ί'έΐΒ Π
3 . 1 .........
•Ρ ·1 · 1 .................... ·έ ." .| .KfKr1 · ! 1 1 { ..ί ή . β . , . ί .. 6 ’ .η χ · 1 · ·Τ ( β ί ζ . S i . i . . S.,=. δ3( . J s . fl. . El9u b a |. |.iE < * u U iV S .d V .. 6 ..- . o .! 9 .1 d .+ = v .ia .ft g z . t . i - e f i x .o .J e . i u i ................ [1.
Εικόνα 17-1. To Dskpatch με την Κεφαλίδα στην Κορυφή.
Περίληψη Επί τέλους, συναντήσαμε τις ρουτίνες του ROM BIOS που βρίσκεται μέσα στον IBM PC μας, και ήδη χρησιμοποιήσαμε δύο από αυτές τις ρουτίνες για να μας βοηθήσουν στην πραγματοποίηση του στόχου μας, δηλαδή να φτιάξουμε το πλήρες πρόγραμμα Dskpatch.
224
Οι Ρουτίνες του ROM BIOS
Π ρώτα μάθαμε για την INT 10h, αριθμός λειτουργίας 6, την οποία χρησιμοποιήσαμε για να καθαρίσουμε την οθόνη. Είδαμε επίσης (αν και πολύ περιληπτικά) ότι αυτή η λειτουργία έχει περισσότερες χρήσεις από αυτές που θα εκμεταλλευτούμε σ ’ αυτό το βιβλίο. Για παράδειγμα, μπορεί τελικά να τη βρείτε χρήσιμη για την κύλιση τμημάτων της οθόνης — στο Dskpatch ή στα δικά σ α ς προγράμματα. Επειτα χρησιμοποιήσαμε τη λειτουργία 2 της INT 10h για να μετακινήσουμε το δρο μέα στην τρίτη γραμμή της οθόνης (αριθμός γρ αμμής 2), όπου αρχίσαμε την εκτύπωση του τομέα μας. Για να κάνουμε τα προγράμματά μας πιο εύχρηστα, ξαναγράψαμε αρκετές διαδικ α σίες έτσι ώ στε να χρησιμοποιούν μεταβλητές μνήμης, αντί για αριθμούς απευθείας σύν δεσης με το hardware. Τώρα, θα μπορούμε να διαβάζουμε άλλους τομείς και να αλ λάζουμε τον τρόπο που δουλεύει το πρόγραμμά μας, αλλάζοντας απλά λίγους αριθμούς στο DSKPATCH.ASM. Τ ελικά, γράψαμε τις διαδικασίες W R IT E _H E A D E R και W RITE STRING, έτσι ώ στε να μπορούμε να εμφανίσουμε μία κεφαλίδα στο άνω μέρος της οθόνης. Ό π ω ς ανα φέρθηκε, θα γράψουμε μια βελτιωμένη έκδοση της W RITE CHAR στο επόμενο κεφάλαιο, αντικαθιστώ ντας τις τελείες στο παράθυρο ASCII της οθόνης μας με χα ρ α κτήρες γραφικών. Και χάρις στον τμηματικό προγραμματισμό, θα το κάνουμε αυτό χωρίς να αλλάξουμε καμμιά από τις διαδικασίες που χρησιμοποιούν τη W R IT E _C H A R .
18 Η ΤΕΛΙΚΗ W RITE_CH AR Μια Καινούργια WRITE CHAR 226 Διαγραφή Μέχρι το Τέλος της Γραμμής 228 Περίληψη 231
225
226
Η Τελική W RITE _ CHAR
Κ ά ν α μ ε εκτενή χρήση των ρουτινών του ROM BIOS στο τελευταίο κεφάλαιο για να καθαρίσουμε την οθόνη και να μετακινήσουμε το δρομέα. Α λλά υπάρχουν πολύ περισ σότερες χρήσεις για το ROM BIOS, και θα δούμε μερικές α π ’ αυτές σ’ αυτό το κεφάλαιο. Χ ρησιμοποιώντας το DOS από μόνο του, δεν μπορέσαμε να εμφανίσουμε όλους τους 256 χαρακτή ρες που μπορεί να εμφανίσει ο IBM PC. Έ τσι, σ ’ αυτό το κεφάλαιο, θα παρουσιάσουμε μια καινούργια έκδοση της W RITE CHAR η οποία εμφανίζει οποιονδήποτε χαρ ακτήρα, χάρις σε μια άλλη λειτουργία της VIDEO ΙΟ. Μ ετά, θα προσθέσουμε μια άλλη χρήσιμη διαδικασία, που ονομάζεται CLEAR ΤΟ _ E N D _ O F LINE, η οποία καθαρίζει τη γραμμή από τη θέση του δρομέα μέχρι τη δεξιά άκρη της οθόνης. Θα τη χρησιμοποιήσουμε στη W RITE HEADER, για να κ α θαρίσουμε την υπόλοιπη γραμμή. Α ς υποθέσουμε ότι πάμε από τον τομέα 10 (δύο ψηφία) στον τομέα 9. Θα παραμείνει στην οθόνη ένα ψηφίο 0 αφού καλέσουμε τη W RITE HEADER για τον τομέα 9. Η CLEAR ΤΟ END OF LINE θα καθαρίσει το ψηφίο αυτό, όπω ς επίσης και ο,τιδήποτε άλλο παραμένει στη γραμμή.
Μια Καινούργια WRITE
CHAR
Η λειτουργία 9 του ROM BIOS για την INT 10h εμφανίζει ένα χαρακτήρα και την ιδιότητά του στην τρέχουσα θέση του δρομέα. Η ιδιότητα ελέγχει χαρακτηριστικά ό πω ς η υπογράμμιση, το αναβόσβημα, και το χρώμα (βλέπε την περιγραφή των διαφορε τικών κω δικών χρ ώ ματος στο εγχειρίδιο της BASIC στην εντολή COLOR). Θα χρησιμοποιήσουμε μόνο δύο ιδιότητες στο Dskpatch: την ιδιότητα 7, η οποία είναι η κα νονική ιδιότητα, και την ιδιότητα 70h, η οποία σημαίνει χρώμα χαρακτήρα μηδέν και χρώμα φόντου 7 και παράγει χαρακτήρες σε αντίστροφη κατάσταση (μαύροι χ αρ ακ τή ρες σε άσπρο φόντο). Μ πορούμε να ρυθμίσουμε τις ιδιότητες ξεχωριστά για κάθε χα ρ α κτήρα, και θα το κάνουμε αυτό αργότερα για να δημιουργήσουμε έναν παραλληλόγραμμο δρομέα σε αντίστροφο χρωματισμό — γνω στό σαν δρομέα σκιά. Για την ώρα όμως, θα χρησιμοποιούμε μόνο την κανονική ιδιότητα όταν εμφανίζουμε ένα χαρακτήρα. Η INT 10h, λειτουργία 9 εμφανίζει το χαρακτήρα και την ιδιότητα στην τρέχουσα θέση του δρομέα. Αντίθετα από το DOS, δεν προχωρεί το δρομέα στην επόμενη θέση, εκτός εάν εμφανίσει περισσότερα από ένα αντίγραφα του χαρακτήρα. Θα χρησιμοποι ήσουμε αυτό το χαρακτηριστικό αργότερα, σε μια άλλη διαδικασία, αλλά τώρα θέλου με μόνο ένα αντίγραφο κάθε χαρακτήρα, γι αυτό θα μετακινήσουμε το δρομέα μόνοι μας. Να η καινούργια έκδοση της WRITE CHAR, η οποία εμφανίζει ένα χαρακτήρα, και μετά μετακινεί το δρομέα ένα χαρακτήρα προς τα δεξιά. Αποθηκεύατε τη στο αρχείο VIDEO IO.ASM: Λ ίσ τα 18-1. Ο ι Α λ λ α γ έ ς τη ς W R I T E - C H A R σ το V ID E O -IO .A S M PUBLIC EXTRN
WRITE_CHAR CURS0R_RI6HT:NEAR
Τ ο βιβλίο τη ς Assembly για τον IBM PC και τους Συμβατούς
227
Λίστα 18-1. συνέχεια Η διαδικασία αυτή εμ φανίζει ένα χαρακτήρα στην οθόνη χρηαψ οποιύντος τ ις ρουτίνες του RON BIOS, έτσι που οι χαρακτήρες σαν την οπισθοδρόμηση να υφίοτανται την ίδια μετα χείριση με τους άλλους, και να εμφανίζονται Η διαδικασία πρέπει να κάνει αρκετή δουλειά για την σνσνέυση της θέσης του δρομέα DL Uses:
Byte για εμφάνιση οτην οθόνη CURSOR_RIGHT
URITECHAR PUSH PUSH PUSH PUSH HOV MOV HOV HOV HOV INT CALL POP POP POP POP RET URITE_CHAR
PROC HEAR ΑΧ BX CX DX AH,9 ΒΗ,Ο CX.l AL.DL BL.7 lOh CURS0RRI6HT DX
;Κλήση για έξοδο χαρακτήρα/ιδιότητας ;Καθορισμός σελίδα ς 0 ;Εμφάνιση ενός μόνο χαρακτήρα ;Χαρακτήρας προς εμφάνιση ;Κανονική ιδιότητα ;Εμφάνιση χαρακτήρα και ιδιότητας ;Μετακίνηση στην επόμενη θέση δρομέα
a BX AX EHDP
Διαβάζοντας αυτή τη διαδικασία, μπορεί να αναρωτηθήκατε γιατί συμπεριλάβαμε την εντολή MOV ΒΗ,Ο. Εάν έχετε έγχρω μο προσαρμογέα οθόνης, ο προσαρμογέας σας έ χει τέσσερις σελίδες κειμένου σε κανονική κατάσταση κειμένου. Θα χρησιμοποιήσου με μόνο την πρώτη σελίδα, τη σελίδα 0. Α υτός είναι ο λόγος ύπαρξης της παραπάνω εντολής. Οσο για το δρομέα, η W R IT E _C H A R χρησιμοποιεί τη διαδικασία CURSOR__RIGHT για να μετακινήσει το δρομέα μια θέση προς τα δεξιά ή στην αρχή της επόμενης γρ αμ μής εάν η κίνηση πήγαινε το δρομέα μετά τη στήλη 79. Τοποθετήστε την ακόλουθη δια δικασία στο CURSOR.ASM: Λ ίστα 18-2. Π ρ ο σ θ έσ τε τη Δ ια δ ικ α σ ία Α υ τή σ το C U R S O R .A S M PUBLIC
CURS0R_RIGHT
; Η διαδικασία αυτή μετα κινεί το δρομέα μία θέση δ εξ ιά , ή στην επόμενη ; γραμμή, αν βρισκόταν στο τέλος της γραμμής.
; ;
; Uses:
SEND_CRLF
\
CURSORRISHT PUSH
PROC ΑΧ
NEAR
228
Η Τελική W RITE _
CHAR
Λίστα 18-2. σ υ ν έ χ ε ι α PUSH PUSH PUSH NOV NOV INT HOV INC CMP JBE CALL JMP ΟΚ: INT DONE: POP POP POP POP RET CURSOR_RI6HT
BX CX DX AH,3 BH.O lOh AH, 2 DL DL.79 OK SEND CRLF DONE lOh DX
;Ανάγνωση της τρέχουοας θέσης του δρομέα ;στη σελίδα 0 ;Ανάγνωση της θέσης του δρομέα ;Καθορισμός νέα ς θέσης δρομέα ;Καθορισμός αριθμού στήλης επόμενης θέσης ;Εξασφάλιση ότι αυτός είν α ι (iO 'ue|iQ (4 | » m ; 6a -i
00J9 Μ +ΞνΓί» I *14 ■< ς Σ Η Μ -ί |[Χ .O0J HQiUtotA 4. 1-11
Press function key, or enter chtracter or hex byte:
Εικόνα 19-1. To Dskpatch με τη Γραμμή Π ροτροπής.
Το βιβλίο τη ς Assembly για τον IBM PC και τους Συμβατούς
243
βλίου, θα επιστρέφουμε και θα μάθουμε καινούργια θέματα, περιμένετε λοιπόν, ή (αν θέλετε) παραλείψτε τα υπόλοιπα κεφάλαια του Dskpatch μέχρις ότου είστε έτοιμοι να γράψετε δικά σας προγράμματα. Ό τ α ν είστε έτοιμοί να επιστρέφετε πάλι, θα βρείτε πολλές χρήσιμες συμβουλές για προγραμματισμό. Φυσικά, αν ανυπομονείτε να γράψετε τις δικές σας διαδικασίες, διαβάστε το επόμε νο κεφάλαιο. Εκεί, θα βρείτε μερικές συμβουλές, και θα σ ας δώσουμε μια ευκαιρία να γράψετε τις διαδικασίες των ακολούθων κεφαλαίων δίνοντάς σας αρκετές λεπτομέρειες για να βάλετε μπρος. Από το Κεφάλαιο 21 και μετά, θα παρουσιάσουμε πολλές διαφορετικές διαδικασίες και θα σας αφήσουμε να ανακαλύψετε πώ ς δουλεύουν. Γιατί; Υπάρχουν δύο λόγοι, και οι δύο σχετίζονται με το να σας κάνουν να σταθείτε στα πόδια σας και να μάθετε πε ρισσότερα για τον προγραμματισμό σε γλώ σσα assembly. Π ρώτα, θέλουμε να έχετε μια βιβλιοθήκη διαδικασιών που να μπορείτε να τις χρησιμοποιήσετε στα δικά σας προ γράμματα. Για να τις χρησιμοποιείτε άνετα πρέπει να εξασκήσετε τις ικανότητές σας. Μετά, παρουσιάζοντας αυτό το μεγάλο παράδειγμα προγραμματισμού, θέλουμε να σας δείξουμε όχι μόνο πώ ς να γράφετε ένα μεγάλο πρόγραμμα, αλλά και να αποκτήσετε μια επαφή μαζί του. Γι αυτό, χρησιμοποιήστε το υπόλοιπο αυτού του βιβλίου με το τρόπο που σας εξυπη ρετεί καλύτερα. Το Κεφάλαιο 20 είναι για όσους από σας ανυπομονούν να γράψουν δι κά τους προγράμματα. Στο Κεφάλαιο 21, θα επιστρέφουμε στο Dskpatch και θα φτιά ξουμε τις διαδικασίες που εκτυπώ νουν και μετακινούν αυτόν που λέμε δρομέα σκιά: ένας δρομέας σε αντίστροφο χρω ματισμό για τη δεκαεξαδική και την ASCII οθόνη.
20 ΜΙΑ ΠΡΟΚΛΗΣΗ ΠΡΟΓΡΑΜΜΑ ΤΙΣΜΟ Υ Οι Δρομείς Σκιές 246 Απλή Διόρθωση 247 Ά λλες Προσθήκες και Αλλαγές στο Dskpatch 248
245
246
Μια Π ρόκληση Π ρογραμματισμού
Λ ^ ,υ τ ό το βιβλίο περιέχει έξι ακόμα κεφάλαια με διαδικασίες. Εάν θέλετε να συνεχί σετε μόνοι σας, διαβάστε αυτό το κεφάλαιο. Θα σ α ς χαράξουμε μια πορεία εδώ, και θα σας δείξουμε το δρόμο μέσα από τα κεφάλαια 21 και 22. Έ π ειτα μπορείτε να προ σπαθήσετε να γράψετε τις διαδικασίες κάθε κεφαλαίου, πριν το διαβάσετε. Αν δεν θέ λετε να προσπαθήσετε να γράψετε τμήματα του Dskpatch ακόμα, παραλείψ τε προς το παρόν αυτό το κεφάλαιο. Είναι πολύ σύντομο και αφήνει πολλές λεπτομέρειες στη φαν τασία σας. Αν αποφασίσετε να το διαβάσετε, να μια πρόταση για το πώ ς να συνεχίσετε: Δ ιαβά στε ένα τμήμα και μετά προσπαθήστε να κάνετε τις δικές σ ας αντίστοιχες αλλαγές στο Dskpatch. Ό τα ν αισθανθείτε ότι κάνατε αρκετή πρόοδο, διαβάστε το κεφάλαιο που έ χει το ίδιο όνομα με τον τίτλο του τμήματος. Αφού το διαβάσετε, μπορείτε μετά να συ νεχίσετε το διάβασμα του επόμενου τμήματος.
Σημείωση: Ισως να θέλετε να κάνετε ένα αντίγραφο όλων των αρχείων σας πριν αρχίσετε τις αλλαγές. Μ ετά, όταν φτάσετε στο Κεφάλαιο 21, θα έχετε τη δυνατό τητα να επιλέξετε αν θα ακολουθήσετε τις αλλαγές, ή αν θα χρησιμοποιήσετε τη δική σας έκδοση.
Οι Δρομείς Σκιές Στο Κεφάλαιο 21 θα τοποθετήσουμε δύο δρομείς σκιές στην οθόνη: έναν στο δεκαε ξαδικό παράθυρο, και έναν στο παράθυρο ASCII. Έ ν α ς δρομέας σκιά είναι παρόμοιος με έναν κανονικό δρομέα, αλλά δεν αναβοσβήνει, το φόντο γίνεται λευκό, και οι χαρα κτήρες μαύροι, όπω ς μπορείτε να δείτε στην Εικόνα 20-1. Ο δρομέας σκιά στο δεκαεξαδικό παράθυρο έχει πλ άτος δύο χαρακτήρες, ενώ αυτός στο παράθυρο ASCII έχει πλάτος ενός μόνο χαρακτήρα. Π ώς δημιουργούμε ένα δρομέα σκιά; Κάθε χαρ ακ τήρ ας στην οθόνη έχει ένα byte ι διότητας. Αυτό το byte λέει στον IBM PC σας πώ ς να εμφανίσει κάθε χαρακτήρα. Έ νας κω δικός ιδιότητας 7h εμφανίζει έναν κανονικό χαρακτήρα, ενώ ο 70h εμφανίζει ένα χαρακτήρα σε αντίστροφο χρωματισμό. Το τελευταίο είναι αυτό που θέλουμε για το δρο μέα σκιά, έτσι το ερώτημα είναι: Π ώς μπορούμε να αλλάξουμε την ιδιότητα των χα ρ α κτήρων μας σε 70h; Η INT 10h λειτουργία 9, εμφανίζει τόσο ένα χαρακτήρα όσο και μια ιδιότητα στην οθόνη, και η INT 10h λειτουργία 8 διαβάζει τον κω δικό του χαρακτήρα στην τρέχουσα θέση του δρομέα. Μπορούμε να δημιουργήσουμε ένα δρομέα σκιά στο δεκαεξαδικό πα ράθυρο με τα ακόλουθα βήματα: •
Αποθήκευση της θέσης του πραγματικού δρομέα (χρησιμοποιήστε την INT 10h λειτουργία 3 για να διαβάσετε τη θέση του δρομέα και να την αποθηκεύσετε σε
Το βιβλίο της Assembly για τον IBM PC και τους Συμβατούς
Disk A
247
Sector 0 00 01 02 03 04 05 08 07 08 09 0Α ΘΒ OC BD 0Ε 0F
00 ■3 1 2 1 02 70 10 20 00 θθ 30 D2 79 40 02 8Ε 50 BF 23 60 Α2 27 70 Ε0 48 88 θθ 5F 98 Β1 ΘΒ 00 Θ3 Α8 Βθ Α1 11 C8 6F 81 D0 F7 26 Εθ 80 Ε4 F8 89 01
90 θθ Βθ ΘΕ C5 7C θθ Εθ BE 9Θ C1 θθ Ε8 ΘΒ Θ3 ΕΒ
49 D0 C4 89 8Ε Β9 BF θθ 73 90 48 Β1 39 θθ 74 55
42 Θ2 5C ΙΕ D5 ΘΒ 70 θθ Θ1 F3 F7 04 θθ Θ3 04 98
4D FD 88 ΙΕ BC θθ 00 Ε8 Β9 Α6 F1 D3 ΕΒ ΟΘ FE 01
20 02 33 80 θθ F3 Β8 86 ΒΒ 75 8Θ Ε8 64 5Α C4 06
20 88 ED 8C 7C Α4 23 0Θ 08 57 3Ε Ε8 88 ΕΒ ΘΑ ΙΕ
33 89 Β8 86 51 1F 7C ΒΒ 98 26 71 3Β 2Β Ε9 CC 00
2Ε θθ ΟΘ 20 FC 08 ΑΒ 80 F3 8Β 81 θθ F0 CD 5Β 11
31 02 07 θθ ΙΕ ΘΕ 91 Θ5 Α6 47 68 FF 76 11 58 2Ε
00 θθ 8Ε θθ 36 2C ΑΒ 53 75 1C 75 36 8D Β9 FF 20
02 0Θ DO 16 C5 ΘΘ Α1 Βθ 62 99 82 ΙΕ Ε8 82 2Ε 88
02 θθ 33 22 36 ΑΒ 16 81 83 ΒΒ ΒΒ 88 26 Βθ 6F C3
81 ΒΒ C9 Β8 78 18 88 Ε8 C7 BE 14 C4 ΒΒ D3 01 Α1
88 ΒΒ ΒΑ Β1 88 88 D1 ΑΒ 15 8Β 96 ΙΕ 52 ΕΒ BE 18
θ 123456789ABCDEF 0 !έΐΒΠ 3.1 008 Ορ *0*8 ο Β - W K + S i S W W i A if ί. " 1 ΟίφίΓ1 iq'A6t6x ittflj iiMn. it 6' Ίχ llDiiJji- T (li; ii i tSjQBlf J « G {4 h'ubiii | < £ h {uUtTG>-8YD4 t^*ig>*Q'u6gia 14 | * m ; 6i -4 0089 i i +=vfll H •u u gz«t«i-i([x .αθί s e s u i e u 4. (-it
Press function key> or enter character or hex byte:
Εικόνα 20-1. Μία Οθόνη με Δρομείς Σκιές. μεταβλητές). Μ ετακίνηση του πραγματικού δρομέα στην αρχή του δρομέα σκιά στο δεκαεξα δικό παράθυρο. • Για τους επόμενους τέσσερις χαρακτήρες, ανάγνωση του κωδικού του χαρ ακ τή ρα (λειτουργία 8) και εμφάνιση, τόσο του χαρακτήρα όσο και της ιδιότητάς του (ορίζοντας την ιδιότητα σε 70h). • Τέλος, επαναφορά του δρομέα στην αρχική θέση. •
Εμφανίζουμε ένα δρομέα σκιά στο παράθυρο ASCII με τον ίδιο περίπου τρόπο. Αφού δημιουργήσετε ένα δρομέα σκιά στο δεκαεξαδικό παράθυρο, μπορείτε να προσθέσετε τον επιπλέον κω δικό για το παράθυρο ASCII. Εχετε υπόψη σας ότι η πρώτη σας προσπάθεια είναι μόνο προσωρινή. Μόλις δημιουρ γήσετε ένα πρόγραμμα, που δουλεύει, με δρομείς σκιές, μπορείτε να γυρίσετε πίσω και να ξαναγράψετε τις αλλαγές σας, έτσι ώστε να έχετε μερικές μικρές διαδικασίες για να κάνετε τη δουλειά σας. Ό τα ν τελειώσετε, κοιτάξτε τις διαδικασίες του Κεφαλαίου 21, για να δείτε έναν τρόπο με τον οποίο μπορούμε να κάνουμε την ίδια δουλειά.
Απλή Διόρθωση Μ όλις δημιουργήσουμε τους δρομείς σκιές, θα θέλουμε να τους μετακινήσουμε πάνω στην οθόνη. Εδώ, πρέπει να προσέξουμε τις οριακές συνθήκες, για να τους κρατήσουμε
248
Μια Π ρόκληση Π ρογραμματισμού
μέσα σε καθένα από τα δύο παράθυρα. Θέλουμε επίσης οι δύο δρομείς σκιές να μετακι νούνται ταυτόχρονα, αφού επροσωπούν τη δεκαεξαδική και ASCII αναπαράσταση του ίδιου πράγματος. Π ώς μπορούμε να μετακινήσουμε κάθε δρομέα σκιά; Καθένα από τα τέσσερα πλή κτρα κατεύθυνσης του δρομέα πάνω στην αριθμητική πληκτροπινακίδα στέλνει, έναν ειδικό αριθμό λειτουργίας: 72 για το δρομέας άνω, 80 για το δρομέας κάτω , 75 για το δρομέας αριστερά, και 77 για το δρομέας δεξιά. Αυτοί είναι οι αριθμοί που πρέπει να προσθέσουμε στην DISPATCH TABLE, μαζί με τις διευθύνσεις των τεσσάρων διαδι κασιών που μετακινούν τους δρομείς σκιές σε καθεμιά από αυτές τις τέσσερις διευ θύνσεις. Για να μετακινήσετε πρα γμ ατικά κάθε δρομέα σκιά, σβήστε τον, μετά αλλάξτε τις δύο συντεταγμένες του και ξαναεμφανίστε τον. Εάν είσασταν προσεκτικοί σ χετικά με το πώ ς εμφανίσατε τους δρομείς σκιές, οι τέσσερις διαδικασίες που τους μετακινούν θα πρέπει να είναι σχετικά απλές. Ό π ο τ ε πληκτρολογείτε ένα χαρακτήρα, το Dskpatch θα πρέπει να διαβάσει αυτόν το χαρακτήρα και να αντικαταστήσει το byte στη θέση του δρομέα σ κιάς με το χα ρ ακ τή ρα που μόλις διαβάστηκε. Να τα βήματα για την απλή διόρθωση: • •
•
Ανάγνωση ενός χαρακτήρα από το πληκτρολόγιο.. Αλλαγή του δεκαεξαδικού αριθμού στο δεκαεξαδικό παράθυρο και του χαρ ακ τή ρα στο ASCII παράθυρο έτσι ώστε να ταιριάζουν στο χαρ ακτήρα που μόλις δια βάστηκε. Αλλαγή του byte στην προσωρινή μνήμη τομέα, SECTOR.
Να μια απλή συμβουλή: Δεν χρειάζεται να κάνετε πολλές α λ λα γές για να προσθέσε τε τη δυνατότητα διόρθωσης. Η Dispatch χρειάζεται λίγο περισσότερο από την κλήση μιας καινούργιας διαδικασίας (την έχουμε ονομάσει EDIT BYTE) η οποία κάνει την πιο πολλή δουλειά. Η EDIT BYTE είναι υπεύθυνη για την αλλαγή τόσο της οθόνης όσο και του SECTOR.
ΤΑ λλες Προσθήκες και Αλλαγές στο Dskpatch Από το Κεφάλαιο 23 μέχρι το Κεφάλαιο 27, οι αλλαγές αρχίζουν να γίνονται κά πω ς εξυπνότερες και πιο πολύπλοκες. Αν ακόμα ενδιαφέρεστε να γράψετε τη δική σ α ς έκ δοση, έχετε υπόψη σας το εξής: Τι περισσότερο θα θέλατε να κάνει το Dskpatch από ότι κάνει τώρα; Χ ρησιμοποιήσαμε τις εξής ιδέες στα υπόλοιπα κεφάλαια. Θέλουμε μια νέα έκδοση της READ BYTE η οποία θα διαβάζει είτε ένα χαρακτήρα είτε ένα διψήφιο δεκαεξαδικό αριθμό και θα περιμένει να πατήσουμε το πλήκτρο Enter πριν επιστρέψει ένα χαρακτήρα στο Dispatch. Αυτό το μέρος της "λίστας επιθυμιών" μας δεν είναι τόσο απλό όσο φαίνεται, και θα αφιερώσουμε δύο κεφάλαια (Κεφάλαια 23 και 24) γι’ αυτό το πρόβλημα. Στο Κεφάλαιο 25, θα κάνουμε ένα κυνήγι λαθών, και μετά στο Κεφάλαιο 26, θα μά θουμε πώ ς να γράφουμε τροποποιημένους τομείς πίσω στο δίσκο χρησιμοποιώ ντας τη
Το βιβλίο τη ς Assembly για τον IBM PC και τους Συμβατούς
249
λειτουργία του DOS INT 26h, η οποία είναι ανάλογη με την INT 25h που χρησιμοποιή σαμε για να διαβάσουμε έναν τομέα από το δίσκο. (Στο Κεφάλαιο 26, δεν θα κάνουμε έλεγχο λαθών ανάγνω σης.) Τέλος, στο Κεφάλαιο 27, θα κάνουμε μερικές αλλαγές στο Dskpatch, έτσι ώστε να μπορούμε να δούμε το άλλο μισό της οθόνης του τομέα μας. Αυτές οι αλλα γές όμως, δεν θα μας επιτρέπουν να κινούμαστε μέσα στην οθόνη του τομέα όσο ελεύθερα θα θέλαμε.
21 ΟΙ ΔΡΟΜΕΙΣ ΣΚΙΕΣ Οι Δρομείς Σκιές 252 Αλλαγή Ιδιότητας Χαρακτήρων 257 Περίληψη 258
251
252
Οι Δ ρομείς Σκιές
^ ■ Ιτο κεφάλαιο αυτό θα φτιάξουμε τις διαδικασίες που εμφανίζουν και σβήνουν ένα δρομέα σκιά στο δεκαεξαδικό παράθυρο, και έναν άλλο στο ASCII παράθυρο. Έ ν α ς δρομέας σκιά ονομάζεται έτσι επειδή δεν είναι ο αρ χικ ός δρομέας του PC. Είναι μια σ κιά... αν και μάλλον ασυνήθιστη, αφού αντιστρέφει το χρω ματισμό του χαρακτήρα, μετατρέποντας το φόντο σε λευκό και το χαρακτήρα σε μαύρο. Στο δεκαεξαδικό π α ράθυρο, έχουμε χώρο να κάνουμε αυτόν το δρομέα τέσσερις χαρακ τήρες πλατύ έτσι ώστε να είναι ευανάγνωστος. Στο παράθυρο ASCII, ο δρομέας σκιά θα έχει πλ άτος μό νον ενός χαρακτήρα, επειδή δεν υπάρχει χώ ρος ανάμεσα στους χαρακτήρες. Έ χουμε πολλές διαδικασίες και πολύ κώ δικα να καλύψουμε εδώ, έτσι θα περιγράψουμε αυτές τις διαδικασίες μόνο περιληπτικά.
Οι Δρομείς Σκιές Η ΙΝΙΤ SEC DISP είναι η μόνη διαδικασία που έχουμε, η οποία αλλάζει την οθό νη του τομέα. Μια καινούργια οθόνη εμφανίζεται όταν αρχίζουμε το Dskpatch, και κάθε φορά που διαβάζουμε έναν καινούργιο τομέα. Αφού οι δρομείς ο κ ιές θα είναι στην οθό νη του τομέα, θα αρχίσουμε τη δουλειά μας εδώ τοποθετώ ντας μια κλήση στη W RITE PHANTOM που βρίσκεται μέσα στην IN IT _ S E C _ D IS P . Μ ’ αυτό τον τρό πο, θα εμφανίζουμε τους δρομείς σκιές κάθε φορά που εμφανίζουμε μια καινούργια ο θόνη τομέα. Να η αναθεωρημένη — και τελική — έκδοση της ΙΝΙΤ SEC DISP στο DISP SEC.ASM: Λ ίσ τα 21-1. Ο ι Α λ λ α γ έ ς τ η ς IN IT -S E C -D IS P σ το D IS P -S E C .A S M PUBLIC
INIT_SEC_DISP
μισού τομέα URITE_PATTERN, SEND_CRLF, DISP_HALF_SECTOR URITE_TOP_HEX_NUMBERS, G0T0_XY, URITE_PHANTOM TOP LINE PATTERN, BOTTOM LINE PATTERN
INIT_SEC_DISP PUSH DL.DL
;Μετακίνηση του δρομέα στη θέση του
Το βιβλίο τη ς Assembly για τον IBM PC και τους Συμβατούς
253
Λ ίσ τα 21-1. σ υ ν έ χ ε ι α LEA CALL CALL XOR
DX,ΤOP_LIΝΕ_ΡATTERN WRITE_PATTERN SEND_CRLF DX.DX
;Αρχή με την αρχή του τομέα
------------W H H W-_SECT0R DX. B0TT0H_LINE_PATTERN WRITE PATTERN
IP INIT_SEC_DISP
ENDP
Παρατηρήστε ότι έχουμε ενημερώσει επίσης την ΙΝΙΤ SEC DISP έτσι ώστε να χρη σιμοποιεί και να αποδίδει αρχικ ές τιμές σε μεταβλητές. Τώρα ορίζει τη SECTOR _ O F F S E T στο μηδέν, για να εμφανίζει το πρώ το μισό ενός τομέα. Ας προχωρήσουμε στην ίδια τη WRITE PHANTOM. Αυτή θα χρειαστεί αρκετή δου λειά. Συνολικά, πρέπει να γράψουμε έξι διαδικασίες, συμπεριλαμβανομένης και της W RITE PHANTOM . Η ιδέα είναι αρκετά απλή, ωστόσο. Π ρώτα, μετακινούμε τον πραγματικό δρομέα στη θέση του δρομέα σκιά, στο δεκαεξαδικό παράθυρο, και αλλά ζουμε την ιδιότητα των επομένων τεσσάρων χαρακτήρω ν σε ανάστροφο χρωματισμό (ιδιότητα 70h). Αυτό δημιουργεί ένα λευκό τμήμα, πλάτους τεσσάρων χαρακτήρω ν, με το δεκαεξαδικό αριθμό σε μαύρο χρώμα. Έ π ειτα κάνουμε το ίδιο στο ASCII παράθυ ρο, αλλά για ένα μόνο χαρ ακτήρα. Τελικά, μετακινούμε τον πρα γμ ατικό δρομέα πίσω, εκεί που ήταν όταν ξεκινήσαμε. Ό λ ες οι διαδικασίες για τους δρομείς σκιές θα είναι στο PHANTOM .ASM , εκτό ς από τη W RITE ATTRIBUTE Ν TIMES, τη διαδικ α σία που θα ορίσει την ιδιότητα των χαρακτήρων. Εισάγετε τις ακόλουθες διαδικασίες στο αρχείο PHANTOM.ASM: Λ ίσ τα 21-2. Τ ο Ν έο Α ρ χ ε ίο P H A N T O M .A S M
C0DE_SE6
SEGMENT PUBLIC
PUBLIC M0V_T0_HEX_P0SITION EXTRN G0T0_XY:NEAR DATASEG SEGMENT PUBLIC EXTRN LINES_BEFORE SECTOR-.BYTE DATA SEG ENDS Η δ ιοδ ικοσ ϊα αυτή μετα κινεί τον πραγματικό δρομέα οτη θέση του δρομέα σκιάς, στο δεκαεξαδικό παράθυρο. Uses: Reads:
GOTO_XY LINES_BEFORE_SECTOR, PHANTOM_CURSOR_X, PHANTOM_CURSOR_Y
MOV TO HEX POSITION
PROC
NEAR
254
Οι Δρομείς Σκιές
Λίστα 21-2. συνέχεια PUSH PUSH PUSH MOV ADO
AX CX DX DH,LINES BEFORE SECTOR DH.2
ADD MOV MOV MOV
DH,PHANTOM CURSOR Y DL.8 CL,3 AL, PHANTOMCURSORX
MUL CL ADD DL.AL CALL GOTO XY POP DX CX POP POP AX RET M0V_T0_HEX_P0SIΤION ENDP PUBLIC EXTRN DATA SEG EXTRN DATA SEG
;Εύρεση γραμμής δρομέα οκιάς ;Συν τη γραμμή δεκαεξαδικϋν και την ;σ ρ ιζό ν τια μπάρα ;0Η = γραμμή του δρομέα σκιάς ;Εσοχή στην αριστερή πλευρά ;Κάθε στήλη χ ρ ειάζεται 3 χαρακτήρες, έτσι ; πρέπει να πολλαπλασιάσουμε ; την CURS0R_X επί 3 ;Και να προσθέσουμε στην εσοχή, για να ; πάρουμε τη στήλη του δρομέα οκιάς
MOV TO ASCII POSITION GOTO XY:NEAR SEGMENT PUBLIC LINES BEFORE SECTOR:BY1 ENDS
Η διαδικασία αυτή μ ετα κινεί τον πραγματικό δρομέα στην αρχή του δρομέα σκιάς στο παράθυρο ASCII. Uses: Reads:
G0T0_XY LINES_BEFORE_SECTOR, PHANTOM_CURSOR_X, PHANTOM_CURSOR_Y PUSH PUSH MOV ADD
AX DX DH,LINES BEFORE SECTOR DH.2
DH,PHANTOM CURSOR Y ADD MOV DL.59 DL,PHANTOM CURSOR X ADD CALL GOTO XY POP DX POP AX RET HOVTOASCIIPOSITION ENDP
; Εύρεση γραμμής δρομέα σκιάς ;Συν τη γραμμή δεκαεξοδικύν kc ο ρ ιζό ντ ια μπάρα ;DH = γραμμή του δρομέα σκιάς ;Εσοχή στην αριστερή πλευρά ;Πρόοθεση της CURSOR_X για να ; τη θέση X του δρομέα σκιάς
Η δ ιαδικασία αυτή αποθηκεύει τη θέση του πραγματικού δρομέα σ τ ις δύο μεταβλητές REAl_CURSOR_X και REAL_CURSO«_Y. W rites:
REAL_CURSOR_X, REAL_CURSOR_Y
SAVE_REAL_CURSOR PUSH AX
PROC
NEAR
Το βιβλίο της Assembly για τον IBM PC και τους Συμβατούς
255
Λίοτα 21-2. συνέχεια PUSH PUSH PUSH HOV ΧΟΗ INT
ΒΧ CX ΟΧ AH,3 ΒΗ,ΒΗ 10Η
;Ανάγνυση της θέοης τουδρομέα ; οτη οελίδα 0 ;Και επιστροφή της οτους DL.DH ;Αποθήκευση της θέσης
SAVE REAL CURSOR
Η διαδικασία αυτή αποκσθιστά τον πραγματικό δρομέα στην παλιά του θέση, που ε ί χ ε αποθηκευτεί σ τ ις REAL_CURSOR_X και REAL_CURSOR_Y. Uses: Reads:
60Τ0_ΧΥ REAL_CURSOR_X, REAL_CURSOR_Y
PUSH DX HOV DL, REAL_CURSOR_Y HOV DH,REAL_CURSOR_X CALL G0T0_XY POP DX RET RESTORE_REAL_CURSOR ENDP PUBLIC EXTRN
URITEPHANTOH URITE_ATTRIBUTE_N_TIMES:NEAR
Η διαδικασία αυτή χρησιμοποιεί τ ις CURS0R_X και CURS0R_Y, μέσα από την H0V_T0_..., οσν τ ις συντεταγμένες του δρομέα σκιάς. Η URITE_PHANTOH εμφανίζει αυτόν το δρομέα ακιά Uses:
URITE_PHANTOM PUSH PUSH CALL CALL
URITE_ATTRIBUTE_N_TIMES, SAVE_REAL_CURSOR RESTORE_REAL_CURSOR. HOV_TO_HEX_POSIΤION HOV_TO_ASCIMPOSITION PROC
a DX SAVE_REAL_CURSOR HOV_TO_HEX_POSIΤION CX.4 DL.70h URITE_ATTRIBUTE_N_T IHES HOV_TO_ASCII_POSIΤION CX.l URITE_ATTRIBUTE_N_TIMES RESTORE REAL CURSOR
;Ιυ ν τ . του δρομέα στο δεκαεξ. παράθυρο ;Πλάτος δρομέα σκιάς τεοσάρυν χαρακτήρων ;Συντ. του δρομέα στο παράθυρο ASCII ;Πλατος δρομέα, εδώ, ενός χαρακτήρα
256
Οι Δρομείς Σκιές
Λίστα 21-2. συνέχεια
WRITE PHANTOM
ENDP
Η διαδικασία αυτή διαγράφει το δρομέα σκιά. Είναι ακριβώς το α ντίθ ετο της WRITE_PHANTOM. Uses:
WRITEATTRIΒΙΓΓΕΝΤ I MES , SAVE_REAL_CURSOR RESTORE_REAL_CURSOR, MOV_TO_HEX_POSITION NOVTOASCIIPOSITION
ERASEPHANTOH PUSH PUSH CALL CALL NOV
PROC NEAR CX DX SAVEREALCURSOR MOV_T0_HEX_P0SIΤION CX,4
MOV CALL CALL MOV CALL CALL POP POP RET ERASEPHANTOM
DL.7 WRITE_ATTRIBUTE_N_TIMES M0V_T0_ASCII_P0SITI0N CX.l WRITE_ATTRIBUTE_N_TIMES RESTORE_REAL_CURSOR DX
;Ιυ ν τ . του δρομέα στο δεκα εξ. παράθυρο ;Αλλαγή. και π ά λ ι, σε λευκό μελάνι και ;μαύρο φόντο
a ENDP
DATA_SEG SEGMENT PUBLIC REALCURSORX DB 0 REAL_CURSOR_Y DB 0 PUBLIC PHANTOM_CURSOR_X, PHANTOM_CURSOR_Y PHANTOMCURSORX PHANTOMCURSORY DATASEG ENDS
Ch W RITE PHANTOM και ERASE PH ANTOM έχουν πολλές ομοιότητες. Στην πραγματικότητα, η μόνη διαφορά είναι η ιδιότητα που χρησιμοποιείται: Η WRITE _ Ρ Η Α Ν Τ Ο Μ ορίζει την ιδιότητα στο 70h για αντίστροφο χρω ματισμό, ενώ η ERASE PHANTOM ορίζει την ιδιότητα πάλι στο κανονικό (7). Και οι δύο αυτές διαδικασίες αποθηκεύουν την παλιά θέση του πραγματικού δρομέα με τη S A V E _ R E A L _ C U R S O R , η οποία χρησιμοποιεί την INT 10h, αριθμός λειτουρ γ ίας 3, για να διαβάσει τη θέση του δρομέα, και μετά αποθηκεύει αυτή τη θέση στα δύο
Το βιβλίο τη ς Assembly για τον IBM PC και τους Συμβατούς
257
byte REAL CURSOR X και REAL CURSOR Y. Αφού αποθηκεύσουν την πραγματική θέση του δρομέα, τόσο η W RITE PHANTOM όσο και η ERASE PHANTOM καλούν μετά τη M O V _ T O _ H E X _ P O S IT IO N , η ο ποία μετακινεί το δρομέα στην αρχή του δρομέα σ κιάς στο δεκαεξαδικό παράθυρο. Με τά, η W RIT E _A T T R IB U T E Ν TIMES εμφανίζει την ιδιότητα του ανάστροφου χρωματισμού για τέσσερις χαρακτήρες, από τη θέση του δρομέα και προς τα δεξιά. Ετσι, ο δρομέας σκιά εμφανίζεται στο δεκαεξαδικό παράθυρο. Με τον ίδιο σχεδόν τρόπο, η WRITE PHANTOM εμφανίζει μετά ένα δρομέα σκιά πλάτους ενός χαρακτήρα στο παράθυρο ASCII. Τ έλος, η R E S T O R E _ R E A L _C U R SO R επαναφέρει τον πραγμ ατικό δρομέα στη θέση που ήταν πριν καλέσουμε τη W RITE PHANTOM . Η μόνη διαδικασία που δεν γράψαμε ακόμα είναι η W RITE A T T R IB U T E _ N _ T IMES, έτσι ας φροντίσουμε γι αυτό τώρα.
Αλλαγή Ιδιότητας Χαρακτήρων Θα χρησιμοποιήσουμε τη W RITE ATTRIBUTE Ν TIMES η οποία θα κάνει τρία πράγματα. Π ρώτα, θα διαβάζει το χαρακτήρα στη θέση του δρομέα. Θα το κάνουμε αυτό επειδή η λειτουργία INT 10h που χρησιμοποιούμε για να ορίσουμε την ιδιότητα ενός χαρακτήρα, η λειτουργία με αριθμό 9, εμφανίζει τόσο το χαρακτήρα όσο και την ιδιότητα στη θέση του δρομέα. Έ τσι, η W RITE ATTRIBUTE Ν TIMES θα αλ λά ζει την ιδιότητα, εμφανίζοντας την καινούργια ιδιότητα μαζί με το χαρακτήρα που μό λις διάβασε. Τ έλος, η διαδικασία θα μετακινεί το δρομέα δεξιά, στην επόμενη θέση, κι έτσι μπορούμε να επαναλάβουμε την όλη σειρά Ν φορές. Μ πορείτε να δείτε τις λε πτομέρειες στην ίδια τη διαδικασία. Α ποθηκεύατε τη W RITE ATTRIBUTE Ν T I MES στο αρχείο V ID E O _IO .A SM :
Λίστα 21-3. Προσθέστε τη Διαδικασία Αυτή στο VIDEO-IO.ASM PUBLIC WRITE_ATTRIBUTE_N_TIHES EXTRN CURS0R_RΙ6ΗΤ:NEAR ; Η διαδικασία αυτή καθορίζει την ιδιότητα για Ν χαρακτήρες, α ρχίζοντα ς ; από την τρέχουσα θέση του δρομέα CX DL ; Uses:
; ;
Αριθμός χαρακτήρυν για τους οποίους καθορίζεται ιδιότητα Νέα ιδιότητα χαρακτήραν
; ;
CURS0R_RI6HT
;
WRITE_ATTRIBUTE_N_TIMES PUSH ΑΧ PUSH BX PUSH CX PUSH DX HOV BL.DL XOR BH.BH HOV DX.CX
PROC
NEAR
Καθορισμός νέα ς ιδιότητος Καθορισμός σελίδα ς οθόνης - 0 0 CX χρησιμοποιείται από τ ι ς ρ ουτίνες του BIOS
258
Οι Δρομείς Σκιές
Λ ίσ τα 21-3. σ υ ν έ χ ε ι α MOV CX.l ΑΤΠΜ.ΟΟΡ: MOV ΑΗ.8 INT 10h MOV AH.9 ΙΜΤ 10h CALL CURSORRIGHT DEC DX JNZ ATTR_LOOP POP DX POP α POP BX POP AX RET WRITE_ATTRIBUTE_H_TIMES
;Κοθορισμός ιδιότητας για ένα χαρακτήρα ;Ανάγνωση χαρακτήρα στη θέση του δρομέα ;Εμφάνιση ιδιότητας και χαρακτήρα ;Καθορισμός ιδιότητας για N χαρακτήρες ; ' 0χ ι , σ υνέχεια
ENDP
Αυτή είναι η πρώτη και τελική έκδοση της W RITE ATTRIBUTE Ν TIMES. Μ ’ αυτή, δημιουργήσαμε επίσης την τελική έκδοση του VIDEO IO.ASM, έτσι δεν θα χρεια στεί να την αλλάξετε ή να την κωδικοποιήσετε ξανά. Disk A
Sector Β 00 01 82 Θ3 84 05, Θ6 Β7 θθ 09 ΒΑ ΘΒ 00 BD ΘΕ 0F
0Β 18 20 30 40 50 60 70 00 90 Α0 Βθ C0 D0 Ε0 F0
IH21 02 00 D2 02 BF Α2 Ε0 00 Β1 00 Α1 6F F7 80 89
70 00 79 ΘΕ 23 27 40 5F ΘΒ Θ3 11 81 26 Ε4 81
98 βθ 00 ΘΕ C5 7C θθ Εθ BE 98 01 θθ ΕΒ ΘΒ Θ3 ΕΒ
49 D0 04 89 8Ε Β9 BF Βθ 73 98 48 Β1 39 ΒΒ 74 55
42 82 50 ΙΕ D5 8Β 78 θθ Θ1 F3 F7 04 θθ 03 04 90
4D FD 08 ΙΕ BC ΘΒ βθ Εθ Β9 Α6 F1 D3 Ε8 D8 FE 01
28 82 33 88 ΒΒ F3 ΒΒ 86 ΘΒ 75 βθ Εθ 64 5Α 04 Θ6
28 88 ED 80 70 Α4 23 8Θ 00 57 3Ε Ε8 ΒΘ ΕΒ 8Α ΙΕ
33 Β9 Β8 06 51 1F 70 ΒΒ 9Θ 26 71 3Β 2Β Ε9 00 θθ
2Ε θθ 0Θ 20 FC 88 ΑΒ 88 F3 ΘΒ 81 88 F8 CD 5Β 11
ΒΒ 02 88 ΘΘ 8Ε D8 θθ 16 36 05 20 βθ ΑΒ Α1 53 Βθ 75 62 10 99 75 Θ2 36 ΙΕ ΘΟ Εθ 11 Β9 Θ2 58 FF 2Ε 2Ε 20 ΘΒ
31 82 87 θθ ΙΕ ΘΕ 91 Θ5 Α6 47 68 FF 76
82 Θ1 ΒΘ ΘΘ 33 09 22 θθ 36 78 ΑΒ 18 16 80 Β1 Εθ 83 07 8Β 8Ε ΒΒ 14 88 04 26 βθ ΘΘ D3 6F 01 03 Α1
θθ ΘΒ ΒΑ Β1 ΒΒ 88 D1 ΑΒ 15 ΒΒ 96 ΙΕ 52 ΕΘ BE 18
B123456789AB0DEF □ΐέΙΒΠ 3 . 1 8 8 0 Βρ *8*8 ο 8 - S 0 3 * L.K+3 || r tM * * ί* *.·■| 8*4* Γ1 IQ'A6f6x Ίllf l/ it 6* , x 1 1 1 * 1 * 1 . τ
ιβις μ ι tsggi*
JMi
k > ub i |§
|ίέϋ*ϋΜϊί>-ΒϊΜ (4 |«Μ8; 6* -A ο6!9 Id + = v f tl I *Μ t+Z je-4{B ■< 5 Z f t * i- i} [ X .HftPSTK DSKPATCH M icrosoft (R) Symbol F ile Generator V ersion 4 .0 0 Copyright (C) M icrosoft Corp .1984, 1985. A ll r ig h t s r eserv ed . Program e n try p o in t a t 0000:0100 Αρχή προγράμματος στη όΐ-ούθυνση 0000:0100
Σ’ αυτή την περίπτωση, το Mapsym έχει δημιουργήσει ένα αρχείο συμβόλων που ονο μάζεται DSKPATCH.SYM. Μ ετά, ξεκινούμε το Symdeb τόσο με το αρχείο συμβόλων όσο και με το αρχείο .COM: A>SYNDCB /S DSKPATCH.SYM OSKPATCH.COM M icrosoft (R) Symbolic Debug U t i l i t y V ersion 4 .0 0 Copyright (C) M icrosoft Corp 1984, 1985. A ll r ig h t s r eserv ed . P rocessor i s [8086] Ο μι,κροεποξοργαστής είναι [8086]
Ο διακόπτης /S , στη διαταγή μας, λέει στο Symdeb να χρησιμοποιήσει το χ α ρ ακ τη ριστικό της ανταλλαγής οθονών. Δεν χρησιμοποιεί εξ ορισμού αυτό το χαρακτηριστι κό, επειδή η ανταλλαγή οθονών μπορεί να κάνει το Symdeb αρκετά αργότερο. Πριν επαναλάβουμε την προηγούμενη διαδικασία διόρθωσης λαθών, α ς ρίξουμε μια γρήγορη ματιά στην αρχή του Dskpatch:
330E:0100 330E:0103 330E:0106 330E:0109 330E:010C 330E:0110 330E:0113
E88C03 E8F402 E81700 E88400 8D160F08 E82D03 E8DA03
CALL CALL CALL CALL LEA CALL CALL
CLEAR_SCREEN WRITE_HEADER READ_SECT0R INIT_SEC_DISP DX.[EDIT0R_PR0MPT] URITE_PR0MPT_L INE DISPATCHER
Τ ο βιβλίο της Assembly για τον IBM PC και τους Συμβατούς
330Ε:0116 CD20
ΙΝΤ
305
20
Μπορείτε να δείτε πόσο βολικά εμφανίζει το Symdeb όλα τα ονόματα, αντί για τις διευ θύνσεις. Οταν αποκω δικοποιήσαμε για τελευταία φορά την DISPATCHER για να βρούμε τη διεύθυνση της εντολής CALL W ORD PTR [ΒΧ], έπρεπε πρώ τα να κοιτάξουμε στο αρ χείο χάρτη για να βρούμε τη διεύθυνση της διαδικασίας, μετά να πληκτρολογήσουμε U 4F0 για να την αποκωδικοποιήσουμε. Με το Symdeb, η ζωή μας γίνεται ευκολότερη: Μπορούμε απλά να πληκτρολογήσουμε U D ISPATCHER για να αποκωδικοποιήσουμε τη διαδικασία μας.
CGROUP:DISPATCHER: 330E:04F0 50 330E:04F1 53 330E: 04F2 52 330E: 04F3 E80401 330E:04F6 0AE4 330E: 04F8 7426 330E:04FA 7807
PUSH PUSH PUSH CALL
READ_BYTE AH. AH DISPATCHER+30 (0520) DISPATCHER+13 (0503)
Μετά από δύο ακόμα διαταγές U, βρίσκουμε την εντολή CALL: 330Ε:0514 330Ε:0517 330Ε:0519 330Ε:051Α 330E:051C
83C303 EBF2 43 FF17 EBD5
ADD JMP INC CALL JMP
BX.+03 DISPATCHER+1B (050B) BX [BX] DISPATCHER+03 (04F3)
Π ληκτρολογήστε G 5 ΙΑ, ό πω ς και πριν, και μετά πατήστε Shift-F5. Εάν έχετε το Symdeb, θα δείτε το Dskpatch να σχηματίζει την οθόνη του. Μετά, θα επιστρέφετε στο Symdeb αφού πατήσετε Shift-F5. Αυτή τη φορά όμως, δεν θα δείτε την οθόνη του Dskpatch, επειδή το Symdeb θα ανταλλάξει τις οθόνες. Για να επιστρέφετε στην οθόνη του Dskpatch, πατήστε το πλήκτρο ( \ ) και μετά Enter. Μ όλις εμφανιστεί η οθόνη του Dskpatch, πα τώ ντας οποιοδήποτε άλλο πλήκτρο θα επιστρέφετε ξανά στην οθόνη του Symdeb. Υ πάρχει ένα λεπτό σημείο, που μπορεί να το παρατηρήσατε, σχετικά με το Symdeb, όπως το χρησιμοποιήσαμε εδώ. Αν κοιτάξουμε στις λίστες της αποκωδικοποίησης, βλέ πουμε εντολές όπω ς η παρακάτω : 330E:051C EBD5
αντί για την:
JMP
DISPATCHER+03 (04F3)
306
Εγγραφή Τ ροποποιημένων Τομέων
330E:051C EBD5
JHP
DISPATCH_LOOP
Γιατί δεν χρησιμοποίησε το Symdeb την ετικέτα DISPATCH LOOP; Δεν ορίσαμε τις ετικέτες σ ’ αυτή τη διαδικασία σαν PUBLIC. Αν γυρίζαμε πίσω και γράφαμε δηλώσεις PUBLIC για όλες τις ετικέτες της DISPATCHER, θα βλέπαμε αυτές τις ετικέτες στη λίστα της αποκω δικοποίησης. (Αν το κάνετε αυτό, θυμηθείτε να ξαναφτιάξετε το αρ χείο συμβόλων με το Mapsym).
Περίληψη Εδώ τελειώνει η συζήτησή μας για τις τεχνικές διόρθωσης. Μ ας απομένουν ακόμα τρία μόνο κεφάλαια. Στο επόμενο κεφάλαιο, θα προσθέσουμε τις διαδικασίες που κυ λούν την οθόνη ανάμεσα στους δύο μισούς τομείς. Έ π ειτα, στα δύο τελευταία κεφά λαια, θα μάθουμε περισσότερα για τις διαφορές μεταξύ των αρχείων .COM και .ΕΧΕ, και θα ρίξουμε μια τελευταία ματιά στην εντολή ASSUME και στις υπερβάσεις τμημάτων. Π αρεμπιπτόντως: Μην ξεχάσετε να διορθώσετε το λάθος που βάλαμε στη DISPATCH TABLE.
27
Ο ΥΠΟΛΟΙΠΟΣ ΜΙΣΟΣ ΤΟΜΕΑΣ Κύλιση κατά Μισό Τομέα 308 Περίληψη 310
307
308
Ο Υ πόλοιπος Μ ισός Τ ομέας
Γ ι α να είναι τέλειο, το Dskpatch θα πρέπει να συμπεριφέρεται σαν ένας επεξεργαστής κειμένου όταν προσπαθείτε να μετακινήσετε το δρομέα κάτω από το τέλος της οθόνης του μισού τομέα: Η οθόνη θα πρέπει να μετακινείται προς τα πάνω κατά μια γραμμή, και να εμφανίζεται στο κάτω μέρος μια καινούργια γραμμή, αλλά εδώ δεν θα θίξουμε τόσο λεπτά σημεία. Σ’ αυτό το κεφάλαιο, θα προσθέσουμε δύο διαδικασίες, τις SCROLL _ U P και SCROLL DO W N , που κυλούν την οθόνη. Οι S C R O L L _U P και SCROLL _ D O W N θα κυλούν την οθόνη κατά μισό τομέα, κι έτσι θα βλέπουμε είτε το πρώ το είτε το δεύτερο μισό του τομέα.
Κύλιση κατά Μισό Τομέα Οι προηγούμενες εκδόσεις των PHANTOM UP και PH A N T O M _D O W N αποκαθιστούν το δρομέα στο πάνω ή στο κάτω μέρος της οθόνης μισού τομέα όποτε προσ πα θήσουμε να μετακινήσουμε το δρομέα έξω από το πάνω ή το κάτω μέρος της οθόνης. Θ α αλλάξουμε τις PHA N TO M U P και PHANTOM DOWN, έτσι ώστε να καλούμε είτε τη SCROLL UP είτε τη SCROLL DOWN όταν ο δρομέας μετακινείται έξω από το πάνω ή το κάτω μέρος της οθόνης. Αυτές οι δύο καινούργιες διαδικασίες θα κυλούν την οθόνη και θα τοποθετούν το δρομέα στην καινούργια του θέση. Να οι τροποποιημένες εκδόσεις των PHANTOM UP και PHANTOM DOWN (στο PHANTOM . ASM): Λ ίσ τα 27-1. Ο ι Α λ λ α γ έ ς σ το P H A N T O M .A S M PHANTOMUP CALL DEC JNS
MOV
m
WASNT_AT_T0P: CALL RET PHANTOMJJP PHANTOMJXJWN CALL INC CMP JB
MOV
PROC NEAR ERASEPHANTOM PHANT0H_CURS0R_Y WASNT_AT_T0P
-,Ήταν στην πόνο-πάνυ. παραμονή εκεί
WRITE_PHANT0H
;Εμγάνιση tou δρομέα στη νέα θέση
ENDP PROC NEAR ERASE_PHANT0M PHANTOMCURSORJT PHANT0M_CURS0R_Y.16 WASNT_AT_B0TT0M
;Διαγραφή στην τρέχουσα θέση ;Μετακϊνηση δρομέα κατά μία γραμμή κάτυ Ήταν στην κάτυ-κατυ; ;Όχι, εμφάνιση δρομέα
PHANTOM_CURS0R_ Y, IS
;Νσι. παραμονή εκεί
1
TTW : ..................... CALL WRITEPHANTOM RET PHANTOMDOWN ENDP
masnt_ at W
;Διαγραφή στην τρέχουσα θέση ;Μετακίνηση δρομέα άνυ, κατά μία γραμμή ;Δεν ήταν στην πάνο-πάνυ, εμφάνισή του
PHANTOM CURSOR Υ.Ο
;Εμφάνιση δρομέα σκιάς
Το βιβλίο τη ς Assembly για τον IBM PC και τους Συμβατούς
309
Μην ξεχάσετε να αλλάξετε την κεφαλίδα σχολίω ν για τις PHANTOM UP και PHANTOM DOWN, για να αναφέρετε ότι αυτές οι διαδικασίες τώρα χρησιμοποιούν τις SCROLL UP και SC R O L L _D O W N : Λ ίσ τα 27-2. Ο ι Α λ λ α γ έ ς σ το P H A N T O M .A S M Αυτές οι τέσ σερ ις δ ια δ ικ α σ ίες μετακινούν τους δ ρομ είς σ κ ιές Χρησιμοποιεί:
ERASE PHANTOM, WRITE PHANTOM
Δ ια βάζει: Γράφει:
1T0M_CURS0R_X, PHANTOM CURSOR Y PHANTOM_CURSOR_X, PHANTOMCURSORY
Οι SCROLL UP και SCROLL DOW N είναι και οι δυο αρκετά απ λές διαδικασίες, αφού φέρνουν στην οθόνη το άλλο μισό του τομέα. Για παράδειγμα, εάν κοιτάζουμε το πρώτο μισό του τομέα, και η P H A N T O M _D O W N καλέσει τη SCROLL UP, θα δούμε το δεύτερο μισό του τομέα. Η SCROLL UP αλλάζει τη SECTOR OFFSET σε 256, την αρχή του δεύτερου μισού του τομέα, μετακινεί το δρομέα στην αρχή της οθό νης του τομέα, εμφανίζει την οθόνη μισού τομέα για το δεύτερο μισό, και τελικά εμφ α νίζει το δρομέα σκιά στο πάνω μέρος αυτής της οθόνης. Μπορείτε να δείτε όλες τις λεπτομέρειες των SCROL1— UP και SCROLL DOWN στην ακόλουθη λίστα. Π ροσθέστε τη στο PHANTOM .ASM . Λ ίσ τα 27-3. Π ρ ο σ θ έσ τε τ ις Δ ια δ ικ α σ ίε ς Α υ τ έ ς σ το P H A N T O M .A S M EXTRN DATA_SE6i EXTRN EXTRN DATA_SEGi
DISP_HALF_SECTOR:NEAR. GOTO_XY:NEAR SEGMENT PUBLIC SECTOR_OFFSET:WORD LINES_BEFORE_SECTOR:BYTE ENOS
Οι δύο α υτές δ ια δ ικ α σ ίες μεταπηδούν μεταξύ τυν δύο οθονυν μισού τομέα Χρησιμοποιεί: Διαβάζει: Γράφει: SCROLLJJP PUSH CALL CALL XOR MOV ADD CALL MOV MOV CALL
WRITE_PHANTOM, DISP_HALF_SECTOR. ERASEPHANTOM, GOTO_XY SAVE_REAL_CURSOR, RESTORE_REAL_CURSOR LINES_BEFORE_SECTOR SECTOR_OFFSET, PHANTOM_CURSOR_Y PRX NEAR DX ERASEPHANTOM SAVE_REAL_CURSOR DL.DL DH,LINES_BEFORE_SECTOR DH.2 60T0_XY DX.256 SECTOR_OFFSET, DX DISP_HALF_SECTOR
;Διαγραφή του δρομέα σκιάς ;Αποθήκευση θέαης πραγματικού δρομέα ;Καθορισμός δρομέα για οθόνη μισού τομέα
;Εμφάνιση δεύτερου μιαού τομέα
310
Ο Υπόλοιπος Μισός Τομέας
Λ ίσ τα 27-3. σ υνέχεια CALL MOV CALL POP RET SCROLLUP
RESTORE_REAL_CURSOR PHANTOH_CURSOR_Y, 0 WRITE_PHANTOH DX
SCROLLDOWH PUSH CALL CALL XOR HOV ADD CALL XOR HOV CALL CALL HOV
PROC NEAR DX ERASEPKANTOH SAVE_REAL_CURS0R DL.DL DH,LINES_BEF0RE_SECT0R DH.2 60T0_XY DX.DX SECT0R_0FFSET, DX DISP_HALF_SECT0R REST0RE_REAL_CURS0R PHANT0H_CURS0R_Y,15
CALL POP RET SCROLL_DOWN
WRITE_PHANT0H DX
;Αποκατάσταση θέσης πραγματικού δρομέα ;Δρομέας στην κορυφή δεύτερου μισού τομέα ;Αποκατάσταση δρομέα σκιάς
ENDP
;Δισγροφή του δρομέα σκιάς .-Αποθήκευση θέσης πραγματικού δρομέα ;Καθορισμός δρομέα για οθόνη μισού τομέα
; Εμφάνιση δεύτερου μισού τομέα ; Αποκατάσταση θέσης πραγματικού δρομέα ;Δρομέας ατο κάτυ μέρος του δεύτερου ; μισού τομέα ;Αποκατάσταση δρομέα σκιάς
ENDP
Oi SCROLL UP και SCROLI DOWN δουλεύουν και οι δύο αρκετά καλά, αν και υπάρχει ένα μικρό πρόβλημα μ ’ αυτές, όπω ς είναι τώρα το Dskpatch. Εκτελέστε το Dskpatch και αφήστε το δρομέα στο πάνω μέρος της οθόνης. Πατήστε το πλήκτρο κα τεύθυνσης του δρομέα προς τα πάνω , και θα δείτε το Dskpatch να ξαναεμφανίζει την οθόνη του πρώτου μισού τομέα. Γιατί; Δεν ελέγξαμε αυτή την οριακή συνθήκη. Το Dskpatch ξαναεμφανίζει την οθόνη όποτε προσπαθήσετε να μετακινήσετε το δρομέα έξω από το πάνω ή το κάτω μέρος της οθόνης μισού τομέα. Να μια πρόκληση για σας: Τροποποιήστε το Dskpatch έτσι, ώστε να ελέγχει δύο ο ριακές συνθήκες. Εάν ο δρομέας σκιά βρίσκεται στο πάνω μέρος της οθόνης του πρώ του μισού τομέα και πατήσετε το πλήκτρο κατεύθυνσης του δρομέα προς τα πάνω , το Dskpatch δεν πρέπει να κάνει τίποτα. Εάν βρίσκεστε στο κάτω μέρος της οθόνης του δεύτερου μισού τομέα και πατήσετε το πλήκτρο κατεύθυνσης του δρομέα πρ ος τα κά τω, ξανά το Dskpatch δεν πρέπει να κάνει τίποτε.
Περίληψη Εδώ τελειώνει η δουλειά μας πάνω στο Dskpatch σ ’ αυτό το βιβλίο. Ο σ κοπός μας ήταν να χρησιμοποιήσουμε το Dskpatch σαν ένα "ζωντανό" παράδειγμα της εξέλιξης ενός προγράμματος σε γλώ σσα assembly, πα ρέχοντάς σας την ίδια στιγμή ένα χρησι μοποιήσιμο πρόγραμμα, και ένα σύνολο διαδικασιών που θα σας φανούν χρήσιμες για τα δικά σας προγράμματα.
Τ ο βιβλίο της Assembly για τον IBM PC και τους Συμβατούς
311
Θα κλείσουμε αυτό το βιβλίο με μια αλλαγή ρυθμού. Στα επόμενα δύο κεφάλαια θα ασχοληθούμε με την επανατοποθέτηση τμημάτων και θα πούμε περισσότερα για τα τμήματα.
Μ
έ ρ ο ς
IV
Υ π ό λ ο ιπ α
28 ΕΠΑΝΑ ΤΟΠΟΘΕΤΗΣΗ Πολλαπλά Τμήματα 316 Επανατοποθέτηση 320 Προγράμματα .COM εναντίον .ΕΧΕ 323
315
316
Επανατοποθέτηση
Z L v a θέμα που πάντα φαίνεται να είναι τυλιγμένο με μυστήριο, είναι η διαφορά με ταξύ αρχείων .ΕΧΕ και .COM και η έννοια των ε πανατοπ οθετήσ εω ν προγραμμάτων. Σαν μέρος της αλλαγής ρυθμού μας σ ’ αυτά το δύο τελευταία κεφάλαια, θα δούμε πώ ς μπορείτε να φτιάξετε προγράμματα μεγαλύτερα από 64Κ — όχι ότι θα το θέλατε α π α ραίτητα', αν και πολλοί το θέλουν.
Π ολλαπλά Τμήματα Μ όλις αρχίσουμε να φτιάχνουμε προγράμματα που χρησιμοποιούν πα ραπάνω από 64Κ μνήμης, διαπιστώνουμε ότι αντιμετωπίζουμε προβλήματα με τα αρχεία .COM. Γιατί; Αυτό ακριβώ ς θα εξετάσουμε εδώ. Π ρώτα α π ’ όλα, κάθε πρόγραμμα πρέπει να φτιάχνεται από ένα ή περισσότερα τμή ματα, όχι πα ραπάνω από 64Κ το καθένα. Π ολλά όμω ς προγράμμ ατα προεκτείνουν τη χρήση της μνήμης τους, χρησιμοποιώ ντας έναν αριθμό διαφορετικών τμημάτων. Για παράδειγμα, ένα τμήμα κώ δικα για το πρόγραμμα, ένα τμήμα δεδομένων για τα δεδο μένα, και ένα τμήμα στοίβας για τη στοίβα και τα προσωρινά δεδομένα. Αν καθένα α π ’ αυτά τα τρία τμήματα χρησιμοποιούνταν πλήρως, θα γεμίζαμε 3*64 = 192Κ μνή μης. Να πώ ς αποκτούμε πρόσβαση σε περισσότερη μνήμη, και να πού παρουσιάζεται η διαφορά μεταξύ προγραμμάτω ν .COM και .ΕΧΕ: τα προγράμματα .ΕΧΕ, έχουν σ χε διαστεί ειδικά γι αυτό το σ κοπό. Ό λ α τα προγράμματά μας σ ’αυτό το βιβλίο ήταν αρχεία .COM, που περιείχαν ένα τμήμα, ή μία ομάδα. Θυμηθείτε, ότι η ψευδολειτουργία GROUP απλά συνδυάζει διαφο ρετικά τμήματα μέσα σε μία μόνο μονάδα, ή οποία ενεργεί σαν ένα τμήμα. Εάν θέλου με να χρησιμοποιήσουμε περισσότερο από ένα τμήμα για να επεκταθούμε σε περισσότερα από 64Κ μνήμης, θα πρέπει να κάνουμε περισσότερη δουλειά. Ας δούμε ένα παράδειγμα. Το πρόγραμμά μας, του Κεφαλαίου 3, που εμφανίζει μία σειρά χαρακτήρω ν είναι ό,τι μας χρειάζεται. Αυτό το παράδειγμα, που είναι γραμμένο με ομάδες στη γλώ σσα assembly, είναι κ ά πω ς έτσι: CGROUP
GROUP ASSUME
C00E_SE6
COOESEG. DATASE6 CS:CGROUP. DS:CGROUP
0R6 WRITESTRIN6 NOV MOV INT INT URITESTRIN6
SEGMENT PUBLIC lOOh PROC FAR AH,9 DX.OFFSETCGROUP:STRING 21h 2Oh ENOP
COOESEG
ENOS
DATA_SEG STRING DB
SEGMENT PUBLIC "Γεια σας, εδύ DOS.$ ”
;Κλήση για έξοδο αλφαριθμητικού ;«όρτοση διεύθυνσης αλφαριθμητικού ; Εμφάνιση αλφαριθμητικού ;Επιατροφή στο DOS
Το βιβλίο της Assembly για τον IBM PC και τους Συμβατούς
317
ENDS
DATA_SE6 END
UtITE_STRING
Τα δύο τμήματα CODE SEG και DATA SEG είναι τοποθετημένα μέσα σε μία μόνο ομάδα των 64Κ, τη CGROUP, κι έτσι η OFFSET CGROUP:STRING δίνει τη σχετική διεύθυνση της STRING, από την αρχή της ομάδας CGROUP. Οταν το DOS φορτώνει ένα πρόγραμμα .COM στη μνήμη, ρυθμίζει και τους τέσσε ρις καταχωρητές τμημάτων (CS, DS, ES και SS) στην αρχή της CGROUP, επομένως η DS:OFFSET CGROUP:STRING είναι ή πλήρης διεύθυνση της STRING. Τι θα γινόταν αν είχαμε δύο διαφορετικά τμήματα και καμία ομάδα; Δεν θα είχαμε το όριο των 64Κ για δύο τμήματα: το όριο θα είτανε 128Κ. Π ώ ς θα ρυθμίζαμε τους καταχω ρητές τμημ ά των ώστε να δείχνουν στα αντίστοιχά τους τμήματα; Χρησιμοποιώντας ένα πρόγραμ μα .ΕΧΕ, που θα μας επιτρέπει να χρησιμοποιούμε διάφορα τμήματα, που όλα τους θα άρχιζαν από διαφορετικές διευθύνσεις. To DOS μας επιτρέπει να ρυθμίσουμε τους κα ταχω ρητές τμημάτων για ένα πρόγραμ μα .ΕΧΕ, με τη βοήθεια μερικών εντολών του assembler. Αυτές οι αναθέσεις, δεν είναι τόσο εύκολες όσο φαίνεται, θα επανέλθουμε όμω ς σ ’ αυτό. Π ρώτα, ας ξαναφτιάξουμε τη WRITE STRING σαν πρόγραμμα .ΕΧΕ. Πρέπει να έχουμε τουλάχιστον δυο τμήματα για κάθε πρόγραμμα .ΕΧΕ: το τμήμα κώδικα, και το τμήμα στοίβας. Αυτά τά δύο τμήματα είναι ειδικές περιπτώσεις για το DOS. To DOS, ρυθμίζει τους τέσσερις κα ταχω ρητές — CS, SS, IP, και SP — όταν φορ τώνει ένα πρόγραμμα .ΕΧΕ στην μνήμη. Ρυθμίζει τον καταχωρητή CS:IP να δείχνει στην πρώτη εντολή της ο ποίας η διεύθυνση εμφανίζεται μετά την ψευδολειτουργία END. Σε ένα πρόγραμμα .ΕΧΕ, αυτή η πρώτη εντολή μπορεί να είναι οπουδήποτε, ενώ σ ’ ένα πρόγραμμα .COM πρέπει να είναι η πρώτη εντολή στο τμήμα κώ δικα. Αντίστοιχα, ο SS:IP δείχνει στο τέλος της περιοχής της στοίβας η οποία ορίζεται από την ψευδολειτουργία SEGMENT STACK. Για παράδειγμα, η έκδοση της W R IT E _ STRING πού ακολουθεί, περιέχει μία στοίβα η οποία έχει μήκος 80 byte, έτσι ο IP θα πάρει την τιμή 80 — το τέλος της περιοχής της σ τοίβας μέσα στο τμήμα στοίβας. Να το πρόγραμμα:
ASSUME C00E_SEG URITE_STRIN6 MOV MOV MOV MOV INT PUSH XOR PUSH
CS:C0DE_SEG, DS:DATA_SEG, SS:STACK_SE6 SEGMENT PUBLIC PROC FAR AX,DATA_SEG OS,AX AH,9 DX,OFFSET STRING Zlh ES ΑΧ,ΑΧ ΑΧ
;Διεύθυνση τμήματος της DATA_SEG Καθορισμός του DS για τη DATA_SEG ;Κλήση για έξοδο αλφαριθμητικού ;Φόρτοση διεύθυνσης αλφαριθμητικού ;Εμφάνιση αλφαριθμητικού ;Αποθήκευση διεύθυνσης επιστροφής για τη μακρινή RET π ιο κάτυ ; Υπάρχει μία INT ZOh στο ES:0
318
Επανατοποθέτηση
;Επιστροφή στο DOS
RET WRITE_STRING
ENDP
C0DE_SEG
ENDS
DATA_SEG STRING DB DATA_SEG
SEGMENT PUBLIC "Γεια σας, εδύ DOS.)' ENDS
STACK_SEG DB STACKSEG
SEGMENT STACK 10 DUP ('STACK ENDS
END
; 'STACK' και τρία κενά διοστήματα
WRITE_STRIN6
Αυτό το πρόγραμμα θα είναι έτοιμο να εκτελεστεί αφού το συνδέσετε, αλλά πρώ τα δια γράψτε το W RITESTR.COM . Εάν έχετε δύο εκδόσεις ενός αρχείου, μία με την προέ κταση .COM, και μία με την προέκταση .ΕΧΕ, το DOS θα εκτελέσει το αρχείο .COM. Υ πάρχουν μερικές διαφορές μεταξύ αυτού του αρχείου .ΕΧΕ, και του αρχικού αρ χείου .COM. Στη θέση της εντολής INT 20h, που επιστρέφει στο DOS, έχουμε τώρα διά φορες δυσνόητες εντολές, με πρώτη την PUSH ES. Οι δύο εντολές PUSH εισάγουν μία διεύθυνση επιστροφής μεγάλου μήκους, την ES:0, επάνω στη στοίβα. Αυτή είναι η διεύ θυνση του πρώτου byte στην περιοχή δεδομένων των 256 byte, την οποία το DOS τοπ ο θετεί μέσα στη μνήμη πριν από το πρόγραμμά μας, και η πρώτη εντολή σ ’ αυτή την περιοχή δεδομένων, είναι μία εντολή INT 20h. Ο καταχωρητής CS πρέπει να δείχνει στην αρχή αυτής της περιοχής δεδομένων όταν εκτελούμε την εντολή INT 20h. Έ τσι συνέβαινε με το πρόγραμμα .COM, από την αρ χή. Ό μ ω ς, το πρόγραμμα Έ Χ Ε αρχίζει με τον καταχωρητή CS ρυθμισμένο στην αρχή του τμήματος κώδικα, και όχι στην περιοχή δεδομένων. Εκτελώντας μία FAR RET στην ES:0, τοποθετούμε στον CS την αρχή της περιοχής δεδομένων και, όπω ς μπορείτε να δείτε, η ES:0 περιέχει την εντολή INT 20h:
39AF:0000 CD20 39AF:0002 006000
ΙΝΤ ADD
20 [BX+SI+00],ΑΗ
Η ψευδολειτουργία CGROUP λείπει, γιατί τώρα έχουμε τρία διαφορετικά τμήματα που δεν είναι περιορισμένα σε μία περιοχή 64Κ ή λιγότερο. Καθένα α π ’ αυτά τα τρία τμήματα, είναι ανεξάρτητο, και κάθε κα ταχω ρητής τμήματος από τους (CS, DS, και SS), δείχνει σε διαφορετικό τμήμα. Τόσο ο CS όσο και ο SS, έχουν ρυθμιστεί από το DOS, όπω ς μπορούμε να δούμε με τη βοήθεια του Debug:
Το βιβλίο τη ς Assembly για τον IBM PC και τους Συμβατούς
319
A>DEW6 IRITESTR.EXE ΑΧ=0000 ΒΧ=0000 CX=0100 DX=0000 SP=0050 ΒΡ=0000 SI=0000 DI=0000 DS=39AF ES=39AF SS=39C3 CS=39BF IP=0000 NV UP 01 PL NZ HA PO NC 39BF:0000 B8C139 MOV AX.39C1
Oi DS και ES, δείχνουν ένα τμήμα χαμηλότερα στη μνήμη, α π ’ ό,τι οι CS και SS. Ό πως είδατε στο Κεφάλαιο 11, τόσο ο DS όσο και ο ES δείχνουν στην περιοχή δεδομέ νων, με μήκος 256 byte, που τοποθετεί το DOS πριν από το πρόγραμμά μας. Στο πρόγραμμα .COM, δεσμεύσαμε αυτή την περιοχή, με μια εντολή ORG 100h. Για τα αρ χεία .ΕΧΕ, δεν χρειάζεται να κάνουμε το ίδιο, επειδή τα τμήματα κώ δικα και δεδομέ νων είναι σε διαφορετικά μέρη της μνήμης. Το τμήμα δεδομένων είναι κάπου αλλού, αλλά ο DS δεν δείχνει στη DATA SEG. Αυτός είναι ο λόγος ύπαρξης της πρώ της εν τολής στη W R IT E _ST R IN G . Η εντολή MOV Α Χ,DATA SEG, μετακινεί τον αριθμό τμήματος του DATA SEG στον καταχωρητή ΑΧ. Εάν κοιτάξουμε στο πρόγραμμά μας στη μνήμη: -« 39BF:0000 39BF:0003 39BF:0005 39BF:0007 39BF:000Α 39BF:000C 39BF:0000 39BF:000F 39BF:0010 39BF:0011
B8C129 8ED8 Β409 ΒΑ0000 CD21 06 33C0 50 CB 0000
M0V MOV MOV MOV INT PUSH XOR PUSH RETF ADD
AX.39C1 DS.AX AH,09 OX,0000 21 ES AX.AX AX [BX+SI].AL
βλέπουμε ότι αυτή η εντολή MOV έχει μεταφραστεί σε MOV AX.39C1, όπου 39C1 είναι ο αριθμός τμήματος του DATA SEG. Χρειαστήκαμε δύο εντολές MOV για να μετακι νήσουμε αυτόν τον αριθμό μέσα στον καταχω ρητή DS, επειδή δεν μπορούμε να μετακι νήσουμε έναν αριθμό κατευθείαν σε οποιονδήποτε καταχω ρητή τμήματος. (Δείτε τον πίνακα των τρόπων καθορισμού διευθύνσεων στο Π αράρτημα Ε.) Από πού προήλθε το 39C1; Σίγουρα, ούτε ο assembler, ούτε ο linker ήξερε εκ των προτέρων, πού θα φόρτωνε το DOS αυτό το πρόγραμμα. Μόνο το DOS μπορεί να το ξέρει αυτό. Και πραγματικά, το DOS είναι αυτό που καθορίζει αυτόν τον αριθμό στο 39C1, η δε διαδικασία του υπολογισμού τέτοιων αριθμών, είναι γνωστή σαν επ ανατοποθέτη ση. To DOS κάνει υπολογισμούς επανατοποθέτησης για προγράμματα .ΕΧΕ, αλλά όχι για προγράμματα .COM. Γι αυτόν το λόγο τα προγράμματα .COM φορτώνονται στην μνήμη πιο γρήγορα. Είναι επίσης πιο συμπαγή, επειδή δεν περιέχουν τις ειδικές πληρο φορίες που χρησιμοποιεί το DOS για να κάνει υπολογισμούς επανατοποθέτησης. Από περιέργεια, ας δούμε τι συμβαίνει εάν δοκιμάσουμε να μετατρέψουμε το .ΕΧΕ πρόγραμμά μας σε πρόγραμμα .COM, χρησιμοποιώντας το Exe2bin:
320
Επανατοποθέτηση
To Exe2bin ξέρει ότι δεν μπορεί να δημιουργήσει ένα πρόγραμμα .COM από το αρ χείο μας, αλλά δεν μας λέει γιατί. Μ ας αφήνει να το βρούμε μόνοι μας. Α ς ρίξουμε μια ματιά στο πρόβλημα. To DOS φορτώνει ένα πρόγραμμα .COM απευθείας στη μνήμη, αφού δημιουργήσει την κεφαλίδα των 256 byte. Εάν θέλουμε διαφορετικά τμήμ ατα, όπω ς στη W RITE _S T R IN G , και θέλουμε να δημιουργήσουμε ένα αρχείο .COM, πρέπει να κάνουμε ο ποιαδήποτε επανατοποθέτηση μόνοι μας, με εντολές μέσα στο πρόγραμμά μας. Δεν είναι πολύ δύσκολο, και θα σας δείξουμε πώ ς γίνεται, έτσι ώ στε να μπορέσετε να πάρε τε μία καλύτερη εικόνα για τον τρόπο με το ν οποίο το DOS επανατοποθετεί προγράμ ματα. Εάν ποτέ χρειαστεί να γράψετε ένα μεγάλο πρόγραμμα .COM το οποίο χρειάζεται να χρησιμοποιήσει παραπάνω από 64Κ μνήμης, θα βρείτε αυτή τη τεχνική χρήσιμη.
Επανατοποθέτηση Ο σκοπός μας είναι να ρυθμίσουμε τον καταχωρητή DS στην αρχή του DATA SEG, και τον καταχωρητή SS στην αρχή του STACK SEGMENT. Μ πορούμε να το κάνου με αυτό με ένα μικρό τέχνασμα. Π ρώτα, πρέπει να βεβαιωθούμε ότι τα τρία τμήματά μας έχουν φορτωθεί στη μνήμη, με τη σωστή σειρά: Τμήμα Κώδικα Τμήμα Δεδομένων Τμήμα Στοίβας Ευτυχώς, έχουμε ήδη φροντίσει γ ι’ αυτό. Ο linker, φορτώνει αυτά τα τρία τμήματα με τη σειρά που εμφανίζονται στο αρχείο μας. Και κάτι που πρέπει να προσέξετε: Ο ταν χρησιμοποιείτε την ακόλουθη τεχνική σε ένα αρχείο .COM για να ρυθμίσετε τους κ α τα χωρητές τμημάτων, βεβαιωθείτε ότι ξέρετε τη σειρά με την οποία το LINK θα φορτώσει τα τμήματά σας. Π ώς υπολογίζουμε την τιμή του DS; Α ς αρχίσουμε κοιτάζοντας σε τρείς ετικέτες που έχουμε τοποθετήσει σε διάφορα τμήματα στην ακόλουθη λίστα. Αυτές οι ετικέτες είναι οι END OF CODE SEG, END OF DAT A SEG και END OF ST ACK SEG. Δεν είναι ακριβώ ς εκεί πού θα περιμένατε να είναι. Γιατί όχι; Λοιπόν, όταν ορίζουμε ένα τμήμα σαν: C00E_SE6
SEGMENT
PUBLIC
δεν λέμε στην κυριολεξία στο linker πώ ς να συρράψει διαφορετικά τμήματα. Έ τσ ι
Το βιβλίο της Assembly για τον IBM PC και τους Συμβατούς
321
αρχίζει κάθε νέο τμήμα σε ένα όριο παραγράφου — σε μια δεκαεξαδική διεύθυνση που τελειώνει με ένα μηδενικό, όπω ς η 32C40h. Επειδή ο linker πηδά στο επόμενο όριο π α ραγράφου κάθε φορά που αρχίζει ένα τμήμα, θα υπάρχει πολύ συχνά μία μικρή κενή περιοχή μεταξύ των τμημάτων. Τ οποθετώ ντας την ετικέτα END OF CODE SEG στην αρχή του DATA SEG, συμπεριλαμβάνουμε αυτή την κενή περιοχή. Εάν είχαμε βάλει την END OF CODE SEG στο τέλος του CODE SEG, δεν θα συμπεριλαμβάναμε την κενή περιοχή μεταξύ των τμημάτων. (Κοιτάξτε τη λίστα απ οκω δικοποίη σης (unassemble) του προγράμμ ατος μας, στη σελίδα 307. Θα δείτε μία κενή περιοχή, γεμισμένη με μηδενικά η οποία έχει μήκος 15 byte.) Ό σ ο για την τιμή του καταχωρητή DS, το DATA SEG αρχίζει στη διεύθυνση 39AF:0130, ή στην 39C2:0000. Η εντολή OFFSET C O D E _ S E G :E N D _ O F _ C O D E _ S E G θα επιστρέφει 130h, που είναι ο αριθμός των byte που χρησιμοποιήθηκαν από την CODE SEG. Διαιρέστε αυτό τον αριθμό με το 16, για να πάρετε τον αριθμό που χρεια ζόμαστε να προσθέσουμε στον DS, έτσι ώστε αυτός να δείχνει στο DATA SEG. Χρη σιμοποιούμε την ίδια τεχνική για να ρυθμίσουμε τον SS. Να η λίστα του προγράμματος μας, που συμπεριλαμβάνει τις εντολές επανατοποθέ τησης που χρειάζονται για ένα αρχείο .COM:
ASSUME
CS:C0DE_SE6. DS:DATA_SEG, SS:STACK_SEG SEGMENT PUBLIC
;Δέσμευση χώρου δεδομένυν για ;πρόγραμμα .COM
100h URITE_STRIMG ΑΧ,OFFSET C0DE_SEG:END_0F_C0DE_SE6 CL,4 ;Υπολογισμός αριθμού παρσγρόφυν τ ΑΧ,CL ; byte για το τμήμα κώδικα K.CS ;Πρόοθεση του CS σ ’ αυτό ;Καθορισμός CS στο DATA_SEG ΒΧ,OFFSET DATA_SEG:END_OF_DATA_SEG BX.CL ;Υπολογισμός ποραγρ. τμήματος δεδομένυν ΑΧ,ΒΧ ; Πρόσθεση στην τιμή του τμήματος δεδομ. SS.AX ;Καθορισμός του SS στο STACK_SE6 ΑΧ,OFFSET STACK_SE6:END_0F_STACK_SE6 SP.AX Καθορισμός SP στο τέλος της στ Γιβας Κλήση για έξοδο αλφαριθμητικού AH.9 DX.OFFSET STRING Φόρτυση διεύθυνσης αλφαριθμητι Εμφάνιση αλφαριθμητικού PUSH XOR PUSH RET URITE_STRING
AX.AX AX ENDP
COOESEG DATA_SEG
SEGMENT PUBLIC
;Αποθήκευση διεύθυνσης επιστροφής ; τη μακρινή RET π ιο κάτυ ; Υπάρχει μία INT 20Η στο ES:0
γιο
322
Επανατοποθέτηση
END_0F_C00E_SE6 STRING DB DATA_SEG
LABEL BYTE "Γεια ο ο ς , εδυ DOS.$” ENDS
STACK_SE6 SEGMENT PUBLIC END_OF_DATA_SEG LABEL BYTE DB 10 DUP ( ’STACK END_OF_STAOC_SEG LABEL BYTE STACK_SE6 ENDS END
’)
; 'STACK' και τρία κενά διαστήματα
URITESTRING
Μ πορείτε να δείτε τα αποτελέσματα όλης αυτής της δουλειάς, με την ακόλουθη σει ρά πράξεω ν του Debug: A>DEBUG *jR.J-flCjSiit*.CQw -U -If 39AF:0100 B83001 39AF:0103 B104 39AF:0105 D3E8 39AF:0107 8CCB 39AF:0109 03C3 39AF:010B 8ED8 39AF:010D BB2000 39AF:0110 D3EB 39AF:0112 03C3 39AF:0114 8ED0 39AF:0116 B85000 39AF:0119 8BE0 39AF:011B B409 39AF:011D ΒΑ0000 -U 39AF:0120 CD21 39AF:0122 06 39AF:0123 33C0 39AF.0125 50 39AF:0126 CB 39AF:0127 0000 39AF:0129 0000 39AF:012B 0000 39AF:012D 0000 39AF:012F 004865 39AF:0132 6C 39AF:0133 6C 39AF:0134 6F 39AF:0135 2C20 39AF:0137 44 39AF:0138 4F 39AF:0139 53 39AF:013A 206865 39AF:013D 7265 39AF:013F 2E 39AF:0140 2400 -G120
MOV MOV SHR MOV ADD MOV MOV SHR ADD MOV MOV MOV MOV MOV
AX.0130 CL, 04 AX,CL BX.CS AX, BX DS.AX BX,0020 EIX, CL AX.BX SS.AX AX,0050 SP.AX tIH.09 DX,0000
INT PUSH XOR PUSH RETF ADD ADD ADD ADD ADD DB DB DB SUB INC DEC PUSH AND JB CS: AND
21 ES AX.AX AX [BX+SI] ,AL BX+SI],AL BX+SI],AL BX+SI],AL BX+SI+65],CL 6C 6C 6F /U.,20 SP DI EIX [BX+SI+65],CH 01A4 AL.00
Το βιβλίο τη ς Assembly για τον IBM PC και τους Συμβατούς
ΛΧ=0950 ΒΧ-0002 DS-39C2 ES-39AF 39AF:0120 C021
CX=0004 DX=0000 SS=39C4 CS=39AF INT 21
SP=0050 IP=0120
323
ΒΡ=0000 SI=0000 DI=0000 NV UP 01 PL NZ ΝΑ P0 NC
Με το να κάνουμε την επανατοποθέτηση για περισσότερα από ένα τμήματα μόνοι μας, έχουμε αυξήσει το ποσό της μνήμης που μπορεί να χρησιμοποιήσει το πρόγραμμα .COM. Οι περισσότεροι ποτέ τους δεν χρειάζονται τέτοια τεχνάσματα, αλλά το να ξέ ρουμε πώς δουλεύει η επανατοποθέτηση μας βοηθάει να καταλάβουμε πώ ς την κάνει το DOS στην περίπτωση των αρχείων .ΕΧΕ.
Προγράμματα .COM εναντίον .ΕΧΕ Θα τελειώσουμε αυτό το κεφάλαιο συνοψίζοντας τη διαφορά μεταξύ αρχείων .COM και .ΕΧΕ. Ένα πρόγραμμα .COM αποθηκευμένο στον δίσκο είναι βασικά μία απεικόνιση του προγράμματος στη μνήμη. Γι’ αυτό, ένα πρόγραμμα .COM είναι περιορισμένο σε ένα μόνο τμήμα, εκτό ς εάν κάνει την δική του επανατοποθέτηση, όπω ς κάναμε εμείς σ ’ αυτό το κεφάλαιο. Ένα πρόγραμμα .ΕΧΕ, από την άλλη μεριά, αφήνει το DOS να αναλάβει την επανα τοποθέτηση. Αυτή η ανάθεση, διευκολύνει πολύ τα προγράμματα .ΕΧΕ, ώστε να χρη σιμοποιούν πολλαπλά τμήματα. Γι αυτόν το λόγο, τα περισσότερα μεγάλα προγράμματα, είναι .ΕΧΕ αντί .COM. Πριν κλείσουμε το θέμα των προγραμμάτω ν .COM εναντίον .ΕΧΕ, α ς ρίξουμε μία πιο κοντινή ματιά στον τρόπο που τα φορτώνει και τα ξεκινάει το DOS. Αυτό θα κάνει τις διαφορές μεταξύ των δύο τύπων προγραμμάτω ν σαφέστερες και πιο συγκεκριμένες. Θα αρχίσουμε με τα προγράμματα .COM. Ό ταν το DOS φορτώνει ένα πρόγραμμα .COM στην μνήμη, ακολουθεί αυτά τα βήματα: • Πρώτα δημιουργεί το πρόθεμα τμήματος προγράμματος (PSP) το οποίο είναι τα 256 byte της περιοχής σημειώσεων που είδαμε στο Κεφάλαιο 11. Μ εταξύ άλλων, αυτό το PSP, περιέχει την γραμμή διαταγής που πληκτρολογείται. • To DOS, έπειτα, αντιγράφει ολόκληρο το αρχείο .COM απ ό το δίσκο στη-μνήμη, αμέσως μετά τα 256 byte του PSP. • Στη συνέχεια, ρυθμίζει και τους τέσσερις καταχω ρητές τμημάτων (CS, DS, ES, και SS) να δείχνουν στην αρχή του PSP. • Τέλος, το DOS ρυθμίζει τον καταχω ρητή IP στο 100h (που είναι η αρχή του πρ ο γράμματος .COM) και τον καταχω ρητή SP στο τέλος του τμήματος — συνήθως στο FFFFE, η οποία είναι η τελευταία λέξη του τμήματος. Αντίθετα, τα βήματα που απαιτούνται για τη φόρτωση ενός αρχείου .ΕΧΕ, είναι κά πως πιο περίπλοκα, επειδή το DOS κάνει την επανατοποθέτηση. Πού βρίσκει το DOS τις πληροφορίες που χρειάζεται για να κάνει την επανατοποθέτηση;
324
Επανατοποθέτηση
Ό π ω ς αποδεικνύεται, κάθε αρχείο .ΕΧΕ έχει μία κεφαλίδα η οποία είναι αποθηκευμένη στην αρχή του αρχείου. Αυτή η κεφαλίδα, ή πίνακας επανατοποθέτησης, έχει πάντα μήκος τουλάχιστον 512 byte, και περιέχει όλες τις πληροφορίες που χρειάζεται το DOS για να κάνει την επανατοποθέτηση. Σε πρόσφατες κυκλοφορίες του macro assembler της, η Microsoft έχει συμπεριλάβει ένα πρόγραμμα, το οποίο λέγεται EXEMOD, που μπο ρούμε να χρησιμοποιήσουμε για να δούμε μερικές από τις πληροφορίες αυτής της κε φαλίδας: A>EXEHOD WRITESTR M icrosoft (R) ΕΧΕ F ile Header U t i l i t y V ersion 4 .0 0 Copyright (C) M icrosoft Corp 1985. A ll r ig h t s r eserv ed . WRITESTR
(hex) ( δ ο κ α ο ί.)
.ΕΧΕ s iz e (b y tes) 290 Μέγοθος apxcCou .EXE (b y te ) Minimun load s i z e (b y te s) 90 Ελάχι-στο μόγοθος φόρτωσης (b y te ) Overlay number 0 Α ριθμός αρχοίου c n ι.κάλυψης I n i t i a l CS:IP 0000:0000 ApxLKn χι,μή CS:IP I n i t i a l SS:SP 0004:0050 Αρχ
Στο τέλος αυτού του πίνακα, μπορείτε να δείτε ότι έχουμε μία μόνο καταχώ ρησ η·επα νατοποθέτησης για το πρόγραμμα WRITESTR. Ο ποιαδήποτε στιγμή κάνουμε μία ανα φορά σε μια διεύθυνση τμήματος, όπω ς κάναμε με τη MOV Α Χ ,DATA SEG, το LINK θα προσθέσει μια καταχώρηση επανατοποθέτησης στον πίνακα. Η διεύθυνση τμήμα τος δεν είναι γνω στή, μέχρι να φορτώσει το DOS το πρόγραμμά μας στη μνήμη, γ ι’ αυ τό και πρέπει να αφήσουμε το DOS να την καθορίσει. Υπάρχουν, επίσης, και μερικές άλλες πληροφορίες στον πίνακα. Για παράδειγμα, οι αρχικές τιμές των CS:IP και SS:SP. Αυτά τα ζευγάρια, μας λένε τις αρ χικ ές τιμές των IP και SP. Ο πίνα κας λέει επίσης στο DOS πόση μνήμη χρειάζεται το πρόγραμμά μας για να μπορέσει να εκτελεστεί: το Ε λάχιστο μέγεθος φόρτωσης. Επειδή το DOS χρησιμοποιεί αυτόν τον πίνακα για να καθορίσει απόλυτες διευθύν σεις τέτοιων τοποθετήσεων σαν διευθύνσεις τμημάτων, υπάρχουν μερικά επιπλέον βή
Το βιβλίο της Assembly για τον IBM PC και τους Συμβατούς
325
ματα που κάνει όταν φορτώνει ένα πρόγραμμα στη μνήμη. Να τα βήματα που ακολουθεί το DOS για να φορτώσει ένα πρόγραμμα .ΕΧΕ: • Δημιουργεί το πρόθεμα τμ ήμ ατος προγράμμ ατος (PSP), όπω ς κάνει για ένα πρό γραμμα .COM. • Δεύτερον, το DOS ελέγχει την κεφαλίδα του αρχείου .ΕΧΕ, για να βρει πού τε λειώνει αυτή, και πού αρχίζει το πρόγραμμα. Έ π ειτα φορτώνει το υπόλοιπο πρό γραμμα στη μνήμη μετά το PSP. • Στη συνέχεια, χρησιμοποιώντας τις πληροφορίες της κεφαλίδας, το DOS βρίσκει και ρυθμίζει όλες τις αναφορές στο πρόγραμμα που πρέπει να επανατοποθετηθούν, όπως είναι οι αναφορές σε διευθύνσεις τμημάτων. • Κατόπιν ρυθμίζει τους καταχω ρητές ES και DS, έτσι ώστε να δείχνουν στη αρχή του PSP. Εάν το πρόγραμμά σ ας, έχει το δικό του τμήμα δεδομένων, πρέπει να αλλάξει τον DS κα ι/ή τον ES, έτσι ώστε να δείχνουν στο τμήμα δεδομένων σας. • Τέλος, το DOS ρυθμίζει τον καταχω ρητή CS στην αρχή του τμήματος κώ δικα, με τον IP ρυθμισμένο από τα στοιχεία της κεφαλίδας του .ΕΧΕ. Με παρόμοιο τρόπο ρυθμίζει τον SS:SP, και πάλι σύμφωνα με τα στοιχεία της κεφαλίδας. Στην περί πτωσή μας, η κεφαλίδα δηλώνει ότι ο SS:SP θα τοποθετηθεί στη θέση 0004:0050. Αυτό σημαίνει ότι το DOS θα ρυθμίσει τον SP στο 0050, και τον SS έτσι, ώστε να δείχνει τέσσερις παραγράφους ψηλότερα στην μνήμη α π ’ ότι το τέλος του PSP.
29
ΠΕΡΙΣΣΟΤΕΡΑ ΓΙΑ ΤΑ ΤΜΗΜΑΤΑ ΚΑΙ ΤΗΝ ASSUME Υπέρβαση Τμήματος 328 Ά λλη μια Ματιά στην ASSUME 330 Λάθη Φάσης 331 Επίλογος 331
327
328
Π ερισσότερα για τα Τ μήματα και την ASSUME
Σ 9 αυτό,
το τελευταίο μας κεφάλαιο, θα ρίξουμε άλλη μια ματιά στην εντολή ASSUME και θα δούμε πώ ς σχετίζεται με τη χρήση των τμημάτων. Στη συνέχεια, θα γνωρίσουμε ένα χαρακτηριστικό που λέγεται υπέρβαση τμήματος (segment override), στο οποίο αναφερθήκαμε πολύ σύντομα. Θα δούμε ότι οι υπερβάσεις τμημάτων πάνε μαζί με την εντολή ASSUME.
Υπέρβαση Τμήματος Μ έχρι τώρα, πάντα διαβάζαμε και γράφαμε δεδομένα που βρισκόταν στο τμήμα δε δομένων. Α σχοληθήκαμε με ένα μόνο τμήμα σ ’ αυτό το βιβλίο (μέσω της χρήσης των ομάδων), έτσι δεν είχαμε κανένα λόγο να διαβάσουμε ή να γράψουμε δεδομένα σε άλ λα τμήματα. Α λλά, όπω ς έχουμε δει, τα προγράμματα .ΕΧΕ περιέχουν πολλαπλά τμήματα, και ακόμα και τα προγράμματα .COM μπορούν να περιέχουν πολλαπλά τμήματα. Έ να κλασσικό παράδειγμα είναι η απευθείας εμφάνιση στην οθόνη: Πολλά εμπορικά προ γράμματα εμφανίζουν στοιχεία στην οθόνη μετακινώ ντας τα δεδομένα απευθείας στη μνήμη της οθόνης και αγνοώ ντας τελείως τις ρουτίνες του ROM BIOS, για χάρη της ταχύτητας. Η μνήμη οθόνης του IBM PC βρίσκεται στο τμήμα JBSOOh για τον προσαρμογέα έγχρωμων γραφικώ ν (color graphics adapter) και στο τμήμα BOOOh για τους μονό χρωμους προσαρμογείς οθόνης. Το να εμφανίσουμε απευθείας στην οθόνη σημαίνει ότι θέλουμε να γράψουμε δεδομένα σε διαφορετικά τμήματα. Σ’ αυτό το τμήμα του κεφαλαίου, θα γράψουμε ένα μικρό πρόγραμμα που δείχνει πώ ς μπορούμε να γράψουμε σε δύο διαφορετικά τμήματα, χρησιμοποιώντας τους κα τα χω ρητές DS και ES για να δείχνουν στα δύο τμήματα. Στην πραγματικότητα, πολλά προ γρ άμματα που γράφουν απευθείας στη μνήμη οθόνης χρησιμοποιούν τον καταχωρητή ES για να δείχνουν στη μνήμη οθόνης. Να το πρόγραμμά μας. Είναι πολύ μικρό, και μπορείτε να δείτε ότι έχει δύο τμήματα δεδομένων, και μια μεταβλητή σε κάθε τμήμα: DATA SEG DS VAR DATA_SEG
SEGMENT PUBLIC DV 1 ENDS
EXTRA SEG ES VAR EXTRA_SEG
SEGMENT PUBLIC DU 2 ENDS
STACK SEG DB STACK_SEG
SEGMENT STACK 10 DUP ('STACK ENDS
C0DE_SE6
SEGMENT PUBLIC CS:COOE SEG. DS:0ATA SEG. ES:EXTRA SEG. SS:STACK_SEG
ASSUME TEST
PROC
FAR
; 'STACK' και τρία κενά διαστήματα
Το βιβλίο της Assembly για τον IBM PC και τους Συμβατούς
329
PUSH
ES
XOR PUSH
AX,AX AX
;Αποθήκευση διεύθυνσης επιστροφής για τη ; μακρινή RET π ιο κάτυ ;Υπάρχει INT 20h στη διεύθυνση ES:0
MOV MOV MOV MOV
AX.DATA SEG DS.AX AX.EXTRA SEG ES.AX
;Διεύθυνση τμήματος για τη DATA_SEG ;Καθορισμός του DS για τη DATA_SEG ;Διεύθυνση τμήματος για την EXTRA SEG ;Καθορισμός του ES για την EXTRA_SEG
MOV MOV
AX.DS VAR BX.ES:ES_VAR
;Ανάγνυση μεταβλητής από το τμήμα δεδομ. ;Ανάγνυση μεταβλητής από το πρόσθετο τμ.
ENDP
; Επιστροφή στο DOS
RET ENDS END
TEST
Θα χρησιμοποιήσουμε αυτό το πρόγραμμα για να μάθουμε και για την ψευδολειτουργία ASSUME, και για τις υπερβάσεις τμημάτων. Παρατηρήστε ότι έχουμε τοποθετήσει τόσο τα τμήματα δεδομένω ν όσο και το τμήμα στοίβας πριν από το τμήμα κώ δικα, και ότι έχουμε επίσης τοποθετήσει την ψευδολειτουργία ASSUME μετά α π ’ όλες τις δηλώσεις τμημάτων. Ό π ω ς θα δούμε σ ’ αυτό το τμήμα του κεφαλαίου, αυτή η διάταξη είναι ένα άμεσο αποτέλεσμα της χρήσης δύο τμη μάτων δεδομένων. Ας ρίξουμε μια ματιά στις δύο εντολές MOV αυτού του προγράμματος: MOV MOV
AX.DSVAR BX.ES:ES_VAR
To ES: μπροστά από τη δεύτερη εντολή λέει στον 8088 να χρησιμοποιήσει τον κα τα χωρητή ES, αντί για τον DS, γι αυτή τη λειτουργία (για να διαβάζει δεδομένα από το πρόσθετο τμήμα μας). Κάθε εντολή έχει έναν εξ ορισμού καταχω ρητή τμήματος, που τον χρησιμοποιεί όποτε αναφέρεται στα δεδομένα. Α λλά, όπω ς κάναμε και με τον κ α ταχωρητή ES, εδώ μπορούμε επίσης να πούμε στον 8088 ότι θέλουμε να χρησιμοποιή σουμε κάποιον άλλον καταχω ρητή τμήμ ατος για τα δεδομένα. Να πώ ς δουλεύει: Ο 8088 έχει τέσσερις ειδικές εντολές, μία για καθέναν από τους τέσσερις καταχω ρητές. Αυτές οι εντολές είναι οι εντολές υπέρβασης τμήματος, και δί νουν εντολή στον 8088 να χρησιμοποιήσει ένα συγκεκριμένο καταχωρητή τμήματος, αντί για τον εξ ορισμού, όποτε η επόμενη εντολή προσπαθεί να διαβάσει ή να γράψει στη μνήμη. Για παράδειγμα, η εντολή MOV AX,ES:ES VAR είναι στην πραγμ ατικότητα κωδικοποιημένη σαν δύο εντολές. Αν αποκω δικοποιήσετε το δοκιμασ τικό μας πρόγραμμα θα δείτε τα ακόλουθα:
330
Π ερισσότερα για τα Τ μήματα και την ASSUME
2CF4:0011 26 DCF4:0012 88 IE0000
ES: HOV
BX.[0000]
Αυτό δείχνει ότι o assembler μετάφρασε την εντολή μας σε εντολή υπέρβασης τμήμα τος, ακολουθούμενη από την εντολή MOV. Τώρα η εντολή MOV θα διαβάσει τα δεδο μένα της από το τμήμα ES, και όχι από το DS. Εάν παρακολουθήσετε (trace) αυτό το πρόγραμμα, θα δείτε ότι η πρώτη εντολή MOV κάνει τον ΑΧ ίσο με 1 P S _ V A R ) και η δεύτερη MOV κάνει τον ΒΧ ίσο με 2 (ES_VA R). Με άλλα λόγια: Δ ιαβάσαμε δεδομένα από δύο διαφορετικά τμήματα.
Ά λ λ η μια Ματιά στην ASSUME Α ς δούμε τι συμβαίνει όταν αφαιρέσουμε το ES: απ ό το πρόγραμμά μας. Αλλάξτε τη γραμμή: MOV
BX.ES:ES_VAR
με την παρακάτω : MOV
BX.ESVAR
Δεν λέμε πια στον assembler ότι θέλουμε να χρησιμοποιήσουμε τον καταχωρητή ES ό ταν διαβάζουμε από τη μνήμη, έτσι θα έπρεπε να αρχίσει να χρησιμοποιεί και πάλι το εξ ορισμού τμήμα (DS), έτσι; Λάθος. Χρησιμοποιήστε το Debug για να δείτε το αποτέλεσμα αυτής της αλλαγής. Θα δείτε ότι έχουμε ακόμα την υπέρβαση τμήματος ES: μπροστά από την εντολή μας MOV. Πώς θα μπορούσε ο assembler να γνωρίζει ότι η μεταβλητή μας είναι στο πρόσθετο τμήμα, και όχι στο τμήμα δεδομένων; Χρησιμοποιώντας τις πληροφορίες που του δώ σαμε με την ψευδολειτουργία ASSUME. Η εντολή ASSUME λέει στον assembler ότι ο κα ταχω ρητής DS δείχνει στο τμήμα DATA SEG, ενώ ο ES δείχνει στο EXTRA SEG. Κάθε φορά που γράφουμε μια εντο λή που χρησιμοποιεί μεταβλητή μνήμης, ο assembler ψάχνει για τη δήλωση αυτής της μεταβλητής για να δει σε ποιο τμήμα είναι δηλωμένη. Μ ετά, ψάχνει μέσα στη λίστα της ASSUME για να βρει ποιος κα ταχω ρητής τμήματος δείχνει σ ’ αυτό το τμήμα. Ο assembler χρησιμοποιεί αυτόν τον καταχω ρητή τμήματος όταν κω δικοποιεί την εντολή. Στην περίπτωση της εντολής MOV BX,ES VAR, ο assembler παρατήρησε ότι η ES VAR ήταν στο τμήμα EXTRA SEG, και ότι ο κα ταχω ρητής ES έδειχνε σ ’ αυτό το τμήμα, κι έτσι δημιούργησε μόνος του μία εντολή υπέρβασης τμήματος ES:. Εάν επρόκειτο να μετακινήσουμε την ES VAR στο STACK SEG, ο assembler θα δημιουρ γούσε μια εντολή υπέρβασης τμήματος SS:. Ο assembler δημιουργεί αυτόματα οποιαδήποτε εντολή υπέρβασης τμήματος χρειαζόμαστε, με την προϋπόθεση φυσικά,
Το βιβλίο τη ς Assembly για τον IBM PC και τους Συμβατούς
331
ότι οι ψευδολειτουργΐες ASSUME αντανακλούν τα πραγμ ατικά περιεχόμενα των κ α τα χωρητών τμήματος.
Λάθη Φάσης Μερικές φορές, θα διαπιστώσετε ότι ο assembler εμφανίζει ένα κρυπτογραφικό μήνυ μα λάθους, όπω ς π.χ. Phase error between passes (Λάθος φάσης μεταξύ περασμάτω ν). Αυτό το μήνυμα μπορεί να σημαίνει διάφορα πρά γμ ατα, αλλά θα δούμε μια συγκεκρι μένη περίπτωση που θα σ ας βοηθήσει να το καταλάβετε. Βασικά, ο assembler περνάει περισσότερες από μία φορές ένα πρόγραμμα καθώ ς π α ράγει την έκδοσή του σε γλώ σσα μηχανής. Μερικές φορές, όπω ς θα δούμε εδώ, το πρό γραμμα αλλάζει μέγεθος μεταξύ των περασμάτω ν. Χρησιμοποιώντας πάλι το δοκιμαστικό μας πρόγραμμα, μετακινήστε τα δύο τμήμα τα δεδομένων (DATA SEG και EXTRA SEG) έτσι ώστε να εμφανίζονται μ ετά το τμή μα κώδικα. Ο assembler τώρα θα κωδικοποιήσει το κύριο πρόγραμμα πριν ακόμα κοιτάξει στα τμήματα δεδομένων. Σαν αποτέλεσμα, θα δημιουργήσει μια κανονική εν τολή MOV για την εντολή MOV BX,ES VAR, επειδή δεν καταλαβαίνει ότι αυτή η με ταβλητή είναι σε άλλο τμήμα. Στη συνέχεια, ο assembler θα κωδικοποιήσει τα δύο τμήματα δεδομένων. Σ ’ αυτό το σημείο, θα αποθηκεύσει την πληροφορία ότι η ES VAR βρίσκεται στο τμήμα EXTRA SEG. Στο επόμενο πέρασμα, ο assembler θα παρατηρήσει ότι τώρα χρειάζε ται χώρο για μια εντολή υπέρβασης τμήματος. Αφού δεν κράτησε χώρο γι αυτή την ε ντολή την πρώτη φορά, δίνει το μήνυμα λάθους: Phase error between passes. Να γιατί τοποθετήσαμε όλα τα τμήματα δεδομένων μας πριν το τμήμα κώ δικα: Για να γνωρίζει ο assembler ποια τμήματα περιείχαν ποιες μεταβλητές. Αυτό που δεν είναι τόσο φανερό, ω στόσο, είναι γιατί βάλαμε την εντολή ASSUME στο CODE SEG, και όχι στην αρχή αυτού του αρχείου. Παίρνουμε επίσης ένα μήνυμα λάθους φ άσης εάν τοποθετήσουμε την ASSUME πρώ τη στο αρχείο. Για κάποιο λόγο (όχι γνω στό σε μας), πρέπει να δηλώνουμε τα τμήματα πριν την ψευδολειτουργία ASSUME, αν θέλουμε να έχουμε εξυπονοούμενες επικαλύψεις τμημάτων. Η πιο ασφαλής προσέγγιση τότε είναι να δηλώσουμε όλα τα δεδομένα πριν από το τμήμα κώ δικα, και να τοποθετήσουμε την ψευδολειτουργία ASSUME στο τμή μα κώδικα.
Επίλογος Μέχρι τώρα έχετε δει πολλά παραδείγματα προγραμμάτων σε γλώ σσα assembly. Σ ’ όλο το βιβλίο, δίναμε συνεχώς έμφαση στον προγραμματισμό, παρά σ τις λεπτομέρειες του μικροεπεξεργαστή 8088 που βρίσκεται μέσα στον προσω πικό υπολογιστή IBM. Α ποτέλεσμα αυτού ήταν να μην γνωρίσετε όλες τις εντολές του 8088, ούτε τις ψευδολειτουργίες του assembler. Αλλά τα περισσότερα προγράμματα σε γλώσσα assembly μπορούν να γραφούν με ότι έχετε μάθει εδώ, και χω ρίς περισσότερες γνώσεις. Η καλύτερη τα
332
Π ερισσότερα για τα Τ μήματα και την ASSUME
κτική για να μάθετε περισσότερα για το γράψιμο προγραμμάτω ν σε γλώ σσα assembly είναι να πάρετε τα προγράμματα αυτού του βιβλίου και να τα τροποποιήσετε. Εάν σκέπτεστε κανένα καλύτερο τρόπο για να γράψετε οποιοδήποτε μέρος του Dskpatch, κάντε το. Έ τσ ι μάθαμε για πρώτη φορά να γράφουμε προγράμματα. Τότε τα προγράμματα ήταν σε BASIC, αλλά η ιδέα ακόμα ισχύει. Βρήκαμε προγράμματα γραμμένα σε BASIC, και αρχίσαμε να μαθαίνουμε για την ίδια τη γλώ σσα ξαναγράφον τας διάφορα κομμάτια αυτών των προγραμμάτων. Μπορείτε να κάνετε το ίδιο με το Dskpatch. Αφού δοκιμάσετε πρώτα μερικά από αυτά τα παραδείγματα, θα είστε έτοιμοι να γρά ψετε δικά σας προγράμματα. Ε πιπλέον, μην αρχίσετε από την αρχή εδώ. Θ α είναι κ ά πω ς δύσκολο την πρώτη σ α ς φορά. Για αρχή, χρησιμοποιήστε τα προγράμματα αυτού του βιβλίου σαν πλαίσιο. Μη φτιάξετε μια τελείως διαφορετική δομή ή τεχνική (τη δική σ ας έκδοση του τμηματικού προγραμματισμού) μέχρι να αισθανθείτε άνετα με το γρ ά ψιμο προγραμμάτων σε γλώ σσα assembly.
ΠΑΡΑΡΤΗΜΑ A ΟΔΗΓΟΣ ΓΙΑ ΤΗΝ ΤΕΑΙΚΗ ΕΚΔΟΣΗ TOY DSKPATCH
334
Ο δηγός για την Τελική Έ κ δ ο σ η του Dskpatch
Η
τελική έκδοση του Dskpatch περιέχει περισσότερα α π ' ό,τι τα παραδείγματα του βιβλίου. Στην πραγματικότητα δεν τελειώσαμε το Dskpatch στο τέλος του κεφαλαίου 27, και είναι πολλά πράγματα που θα έπρεπε να είχαμε συμπεριλάβει για να το κάνουμε ένα εύχρηστο πρόγραμμα. Το Π αράρτημα Β περιέχει την τελική έκδοση. Α ς ρίξουμε μία γρήγορη ματιά στο τι θα βρείτε εκεί. Ο πω ς είναι μέχρι τώρα, το Dskpatch μπορεί να διαβάσει μόνο τον επόμενο ή προη γούμενο τομέα. Έ τσι, εάν θέλετε να διαβάσετε τον τομέα 576, θα πρέπει να πατήσετε το πλήκτρο F2 575 φορές. Αυτό σημαίνει πολλή δουλειά. Και αν θέλατε να ψάξετε σε τομείς μέσα σε ένα αρχείο; Ό π ω ς έχει η κα τάσταση, θα πρέπει να ψάξετε στον τομέα του καταλόγου και να βρείτε πού θα κοιτάζατε για τους τομείς αυτού του αρχείου. Και πάλι πολλή δουλειά. Η τελική έκδοση του Dskpatch μπορεί είτε να διαβάσει απόλυτους τομείς, όπω ς και η μέχρι τώρα έκδοση του βιβλίου, ή να διαβάσει τομείς μέσα σε ένα αρχείο. Στην προχωρημένη του μορφή το Dskpatch είναι ένα πολύ εύχρηστο πρόγραμμα. Η προχωρημένη έκδοση έχει πολλές αλλαγές που δεν μπορούν να περιγραφούν λε πτομερώς εδώ, γ ι’ αυτό ας ρίξουμε μια ματιά σ τις καινούργιες λειτουργίες που προσθέ σαμε. Θα βρείτε πολλές από τις αλλαγές εξερευνώντας το Dskpatch και κάνοντας δικές σας. Το τελικό Dskpatch χρησιμοποιεί τώρα οκτώ πλήκτρα λειτουργιών. Είναι δύσκολο να τα θυμάστε, εάν δεν χρησιμοποιήτε το Dskpatch πολύ συχνά, έτσι αυτό εμφανίζει μια "γραμμή πλήκτρων" στο κάτω μέρος της οθόνης. Να μια περιγραφή των πλήκτρω ν λειτουργιών: F1.F2
χρησιμοποιήθηκαν σ ’ αυτό το βιβλίο. To F1 διαβάζει τον προηγούμενο το μέα, και το F2 τον επόμενο.
F3
αλλάζει τον αριθμό ή το γράμμα του οδηγού δίσκου. Α πλά πατήστε F3 και εισάγετε ένα γράμμα, ό πω ς π.χ. το Α (χωρίς την άνω-κάτω τελεία, (:), ή εισάγετε έναν αριθμό του οδηγού, όπω ς 0. Ό τα ν πατήσετε το πλή κτρο Enter, το Dskpatch θα αλλάξει οδηγό και θα διαβάσει ένα τομέα α πό τον καινούργιο οδηγό δίσκου. Μπορεί να θέλετε να τροποποιήσετε το Dskpatch, έτσι ώ στε να μην διαβάζει ένα νέο τομέα όταν αλλάζετε οδηγό. Το ρυθμίσαμε έτσι ώστε να είναι πολύ δύσκολο να γραφεί ένας τομέας σε λάθος δίσκο.
F4
αλλάζει τον αριθμό τομέα. Α πλά πατήστε F4 και πληκτρολογήστε ένα νού μερο σε δεκαδική μορφή. To Dskpatch θα διαβάσει αυτόν τον τομέα.
F5
υπάρχει στο βιβλίο. Π ατήστε τα πλήκτρα Shift και F5 για να γράψετε ένα τομέα πίσω στον δίσκο.
F6
αλλάζει το Dskpatch σε κα τάσταση αρχείου. Α πλά εισάγετε το όνομα του αρχείου και το Dskpatch θα διαβάσει ένα τομέα από το αρχείο. Α πό εκεί και μετά, τα F1 (Προηγούμενος τομέας) και F2 (Επόμενος τομέας) δια
Το βιβλίο της Assembly για τον IBM PC και τους Συμβατούς
335
βάζουν τομείς από αυτό το αρχείο. To F3 κλείνει την κατάσταση αρχείου και επαναφέρει στην κα τάσταση απόλυτου τομέα. F7
ζητάει μια σχετική διεύθυνση μέσα σ' ένα αρχείο. Είναι σχεδόν σαν το F4 (Τομέας) εκτό ς του ότι διαβάζει τομείς μέσα σε ένα αρχείο. Εάν εισά γετε μια σχετική διεύθυνση 3, το Dskpatch θα διαβάσει τον τέταρτο τομέα στο αρχείο σας.
F10
έξοδος από το Dskpatch. Εάν κατά λάθος πατήσετε αυτό το πλήκτρο, θα ανακαλύψετε ότι βρεθήκατε πίσω στο DOS, και θα χάσετε οποιεσδήποτε αλλαγές που έχετε κάνει στον τελευταίο τομέα. Μπορεί να θέλετε να αλ λάξετε το Dskpatch, έτσι ώστε να ρωτάει εάν πραγμ ατικά θέλετε έξοδο.
Ένας αριθμός άλλω ν αλλαγώ ν δεν είναι τόσο φανερές όπω ς αυτές που μόλις ανα φέρθηκαν. Για παράδειγμα, το Dskpatch τώρα κυλάει την οθόνη μια γραμμή κάθε φο ρά. Εάν μετακινήσετε το δρομέα στην τελευταία γραμμή της οθόνης και πατήσετε το πλήκτρο κάτω-βέλος, το Dskpatch θα κυλήσει την οθόνη κατά μια γραμμή, τοποθετών τας μια νέα γραμμή στο τέλος. Επιπλέον, τώρα χρησιμοποιούνται και μερικά άλλα πλήκτρα του πληκτρολογίου: Home μετακινεί το δρομέα σκιά στο πάνω μέρος της οθόνης μισού τομέα και κυλάει την οθόνη, έτσι ώστε να βλέπετε τον πρώ το μισό τομέα. End μετακινεί τον δρομέα σκιά στο κάτω δεξιά σημείο της οθόνης μισού τομέα και κυλάει την οθόνη, έτσι ώστε να βλέπετε το δεύτερο μισό τομέα. PgUp κυλάει την οθόνη μισού τομέα κατά τέσσερις γραμμές. Π ρόκειται για μία πολύ εξυπηρετική ιδιότητα όταν θέλετε να μετακινηθείτε σε κάποιο ενδιάμεσο σημείο της ο θόνης τομέα. Εάν πατήσετε PgUp τέσσερις φορές, θα δείτε τον τελευταίο μισό τομέα. I'gDn κυλάει την οθόνη μισού τομέα κατά τέσσερις γραμμές, στην αντίθετη κατεύ θυνση από το PgUp. Εάν θέλετε, μπορείτε να τροποποιήσετε το τελικό Dskpatch, έτσι ώστε να ταιριάζει καλύτερα στις δικές σας ανάγκες. Γι αυτό, το Π αράρτημα Β περιέχει τις λίστες όλων των πηγαίων αρχείων. Μ πορείτε λοιπόν να τροποποιήσετε το Dskpatch με οποιοδήποτε τρόπο και να διδαχθείτε από ένα πλήρες παράδειγμα. Για παράδειγμα, μπορείτε να βελ τιώσετε τις ικανότητες ελέγχου λαθών. Ό π ω ς είναι τώρα, αν πα τώ ντας F2 σας κάνει να υπερβείτε το τέλος του δίσκου ή αρχείου, το Dskpatch δεν επαναφέρει τον τομέα στον τελευταίο τομέα του δίσκου ή αρχείου. Εάν έχετε φιλοδοξίες, δείτε εάν μπορείτε να τρο ποποιήσετε το Dskpatch ώστε να συλλαμβάνει και να διορθώνει τέτοια λάθη. Ή μπορείτε, αν θέλετε, να επιταχύνετε την ενημέρωση της οθόνης. Για να το κάνετε αυτό πρέπει να ξαναγράψετε μερικές διαδικασίες, όπω ς τις W R IT E _C H A R και WRITE ATTRIBUTE Ν TIMES, για να γράφουν κατευθείαν στη μνήμη οθόνης. Τώ
336
Ο δηγός για την Τελική Έ κ δ ο σ η του Dskpatch
ρα χρησιμοποιούν τις πολύ αργές ρουτίνες του ROM BIOS. Εάν είσαστε πραγμ ατικά φιλόδοξος, προσπαθήστε να γράψετε τις δικές σ ας ρουτίνες εξόδου χαρακτήρω ν, που να στέλνουν χαρακτήρες στην οθόνη πολύ γρήγορα. Καλή τύχη. ύίσκος C
Τομέας 0 00 01 02 03 04 05 06 07 08 09 0R 0B 0C 00 0E 0F
1 00 | 3 | 3 4 90 40 53 44 4F 53 10 02 00 02 07 R3 F 8 29 00 20 00 00 00 00 00 00 00 00 30 00 00 00 00 01 00 FR 33 40 ΒΒ 78 00 38 C5 37 1E 56 50 FC AC 26 80 3D 00 74 03 60 06 1F 89 47 02 C7 07 2B 70 72 66 Π0 10 7C 98 F 7 26 80 0Ε 7C A3 3F 7C R3 37 7C 90 ΙΕ 0Β 7C 03 C3 48 F 7 F3 3F 7C Ε 8 94 00 Β0 01 E 8 R0 Β0 00 BE Ε 6 7D F3 R6 75 0D C0 00 F3 Α6 14 18 BE 87 7D D0 1F 8F 04 8F 44 02 CO 19 Ε0 33 D2 F 7 36 0Β 7C F E C0 F0 7C ΒΒ 00 07 m 37 7C EB
33 11 00 C0 16 26 7C 16 B8 01 R9 80 E8 BE R2 3F
2E 00 00 8E 53 8fl FB 7C 20 06 00 7F 61 D0 3C 00
32 04 00 D0 BF 05 8fl 03 00 37 72 20 00 70 7C fl1
00 00 00 BC 2B RR 16 06 F7 7C 19 BE 32 EB Π1 18
02 11 00 00 7C 8R FD 1C 26 BB 88 F1 E4 EB 37 7C
04 00 00 7C B9 C4 70 7C 11 00 FB 70 CD Π1 7C 2R
01 00 00 16 0B E2 CD 03 7C 05 B9 B9 16 1C fl3 06
00 00 0F 07 00 FI 13 06 8B fll 0B 08 5E 05 30 38
0123456789RBCDEF g4PNSDOS3.2 90Q i β·μ°) i o i 8 s . 3 iqiui iix 6f7AU S ,+ ! f l i nufifl= tdfin*qn-e± rf ίίμί?!μ 7^ ^ ! Μ A