[Chapter Three][Previous][Chapter Four] [Art of Assembly][Randall Hyde]

Art of Assembly: Κεφαλαιο 3


3.4. I/O   Είσοδος/Έξοδος.

3.5. Διακοπές και Ε/Ε με σφυγμομέτρηση.
 


3.4. I/O  (Εισοδος/Έξοδος).

Υπάρχουν τρεις βασικές φόρμες για είσοδο και έξοδο που ένα τυπικό σύστημα Η/Υ χρησιμοποιεί : Είσοδος/Έξοδος- Απεικονισμένη στην Είσοδο-Έξοδο (I/O-mapped I/O), Ε/Ε Απεικονισμένη στην Μνήμη (Memory-mapped I/O) και Μνήμη Άμεσης Προσπέλασης (Direct Memory Access-DMA) .
Η Ε/Ε-Απεικονισμένη Ε/Ε χρησιμοποιεί ειδικές εντολές για να μεταφέρει δεδομένα ανάμεσα στο σύστημα του Η/Υ και το έξω κόσμο. Η Ε/Ε απεικονισμένη στην Μνήμη χρησιμοποιεί ειδικές θέσεις μνήμης στον κανονικό χώρο διευθύνσεων της CPU για να επικοινωνεί με τις  πραγματικές μηχανές. Η DMA είναι μια ειδική μορφή της Ε/Ε απεικονισμένης στην μνήμη, όπου οι περιφερειακές μηχανές διαβάζουν και γράφουν μνήμη χωρίς να περάσουν μέσω της CPU. Ο κάθε μηχανισμός  Ε/Ε έχει τα δικά του πλεονεκτήματα και μειονεκτήματα. Με αυτά θα ασχοληθούμε παρακάτω.

Το πρώτο πράγμα που πρέπει να ξέρουμε για το υποσύστημα Ε/Ε είναι  η Ε/Ε μιας υψηλού επιπέδου γλώσσας προγραμματισμού. Σ’ ένα πραγματικό σύστημα Η/Υ σπάνια θα βρείς εντολές μηχανής που να συμπεριφέρονται όπως το writeln, printf ή ακόμη του x86 οι get και put εντολές . Στην πραγματικότητα, οι περισσότερες εντολές Ε/Ε συμπεριφέρονται ακριβώς όπως η εντολή mov σ’ έναν x86. Για να στείλει δεδομένα σε μια συσκευή εξόδου, η CPU απλούστατα μετακινεί αυτά τα δεδομένα σε μια ειδική θέση μνήμης (στον χώρο διευθύνσεων της Ε/Ε, αν έχουμε Ε/Ε-απεικονισμένη Ε/Ε ή σε μια διεύθυνση στον χώρο διευθύνσεων της μνήμης, αν χρησιμοποιούμε Ε/Ε απεικονισμένη στην μνήμη. Για να διαβάσει δεδομένα από μια συσκευή εισόδου, η CPU απλά μετακινεί τα δεδομένα από την διεύθυνση (Ε/Ε ή μνήμης ) αυτής της συσκευής στην CPU.

Μια θύρα Ε/Ε είναι μια συσκευή που μοιάζει με κελί μνήμης αλλά περιλαμβάνει διασυνδέσεις με τον εξωτερικό κόσμο. Μια θύρα Ε/Ε τυπικά χρησιμοποιεί ένα μανδαλωτή ή buffer και όχι flip-flop για να υλοποιήσει το κελί μνήμης. Όταν η CPU γράφει στην διεύθυνση που σχετίζεται με το μανδαλωτή, ο απομονωτής συλλαμβάνει τα δεδομένα και τα θέτει διαθέσιμα σε μια ομάδα εξωτερικών συρμάτων για την CPU και το σύστημα μνήμης.
 

 
 

Σημείωσε ότι οι θύρες Ε/Ε είναι write, read-only. Η θύρα στο παραπάνω σχήμα για παράδειγμα , είναι write-only θύρα. Εφόσον τα αποτελέσματα στο μανδαλωτή δεν ξαναγυρίζουν πίσω στην δίαυλο δεδομένων της CPU ,η CPU δεν μπορεί να διαβάσει τα δεδομένα που περιέχει ο buffer. Και ο αποκωδικοποιητής διευθύνσεων και οι γραμμές ελέγχου του write πρέπει να είναι ενεργοί έτσι ώστε να λειτουργήσει o μανδαλωτής. Όταν διαβάζει από την διεύθυνση, η γραμμή αποκωδικοποίησης είναι ενεργή, αλλά η γραμμή ελέγχου write δεν είναι.

Το επόμενο σχήμα δείχνει πώς να δημιουργήσετε μια read/write θύρα Ε/Ε. Τα δεδομένα που είναι γραμμένα στην θύρα εξόδου επιστρέφουν σε μια προφανή θύρα. Οποτεδήποτε η CPU διαβάζει τις αποκωδικοποιημένες διευθύνσεις, οι γραμμές read και decode είναι ενεργές και αυτό ενεργοποιεί την χαμηλότερη θύρα. Αυτό τοποθετεί τα δεδομένα, τα οποία προηγουμένως είχαν γραφεί στην θύρα εξόδου, στην δίαυλο δεδομένων της CPU, αφήνοντας την CPU να διαβάσει τα δεδομένα. Μια read-only θύρα είναι απλά το χαμηλότερο μισό αυτού του σχήματος. Το σύστημα αγνοεί οποιοδήποτε δεδομένο που είναι γραμμένο σε θύρα εισόδου.
 

 

 
 

Γενικά, μια δοσμένη περιφερειακή συσκευή χρησιμοποιεί περισσότερες από μια θύρες Ε/Ε. Μια τυπική παράλληλη διασύνδεση εκτυπωτή, για παράδειγμα, χρησιμοποιεί τρεις θύρες : μια read/write θύρα, μια θύρα εισόδου και μια θύρα εξόδου. Η θύρα read/write είναι η θύρα των δεδομένων. Η θύρα εισόδου επιστρέφει σήματα ελέγχου από τον εκτυπωτή. Αυτά τα σήματα δείχνουν αν ο εκτυπωτής είναι έτοιμος να δεχθεί ακόμη έναν χαρακτήρα, αν είναι εκτός λειτουργίας, αν έχει τελειώσει το χαρτί κτλ. Η θύρα εξόδου μεταβιβάζει πληροφορίες ελέγχου στον εκτυπωτή για το αν τα δεδομένα είναι διαθέσιμα για εκτύπωση.

Για τον προγραμματιστή, η διαφορά μεταξύ των διαδικασιών της Ε/Ε-απεικονισμένης Ε/Ε  και της Ε/Ε απεικονισμένης στην μνήμη είναι η εντολή που χρησιμοποιεί. Για την Ε/Ε-απεικονισμένη στην μνήμη, κάθε εντολή που προσπελαύνει μνήμη μπορεί να προσπελάσει την θύρα της Ε/Ε απεικονισμένης στην μνήμη. Στο x86, οι εντολές mov, add, sub, cmp, and, or και not μπορούν να διαβάσουν μνήμη. Οι εντολές mov και not μπορούν να γράψουν δεδομένα στην μνήμη. Η Ε/Ε-απεικονισμένη Ε/Ε χρησιμοποιεί ειδικές εντολές για να προσπελάσει μια θύρα Ε/Ε. Π.χ. η CPU του x86 χρησιμοποιεί τις εντολές get και put , η οικογένεια του Intel 80x86 χρησιμοποιεί τις εντολές in και out.Οι εντολές in και out του 80x86 δουλεύουν όπως ακριβώς και η εντολή mov με την διαφορά ότι τοποθετούν την διεύθυνση τους στην δίαυλο διευθύνσεων Ε/Ε και όχι στην δίαυλο διευθύνσεων της μνήμης.


3.5. Διακοπές και Ε/Ε με σφυγμομέτρηση.

Πολλές συσκευές Εισόδου/Εξόδου δεν δέχονται δεδομένα με αυθαίρετο ρυθμό. Για παράδειγμα ένα PC βασισμένο σε Pentium είναι ικανό να στέλνει αρκετά εκατομμύρια χαρακτήρες το δευτερόλεπτο στον εκτυπωτή, αλλά ο εκτυπωτής είναι (μάλλον) ανίκανος να εκτυπώνει τόσους πολλούς χαρακτήρες το δευτερόλεπτο. Παρομοίως, μια συσκευή εισόδου όπως είναι το πληκτρολόγιο, δεν έχει την δυνατότητα να παρέχει αρκετά εκατομμύρια κτυπήματα πλήκτρων κάθε δευτερόλεπτο. Η CPU χρειάζεται κάποιο μηχανισμό για να συντονίσει την μεταφορά δεδομένων μεταξύ του συστήματος του Η/Υ και της περιφερειακής του συσκευής.

Ένας συνηθισμένος τρόπος για να συντονίσεις την μεταφορά δεδομένων, είναι να παρέχεις μερικά bits κατάστασης σε μια δευτερεύουσα θύρα εισόδου.Για παράδειγμα, η τιμή 1 σ’ ένα bit σε μια θύρα Ε/Ε ειδοποιεί την CPU ότι ο εκτυπωτής είναι έτοιμος να δεχθεί και άλλα δεδομένα, το 0 υποδεικνύει ότι ο εκτυπωτής είναι απασχολημένος και ότι η CPU δεν πρέπει να στείλει άλλα δεδομένα στον εκτυπωτή.

Υποθέστε ότι η θύρα των δεδομένων του εκτυπωτή είναι τύπου Εισόδου/Εξόδου απεικονισμένης στην Μνήμη στην διεύθυνση OFFEOh και η θύρα της κατάστασης του εκτυπωτή είναι το bit 0 της θύρας Ε/Ε απεικονισμένης στην μνήμη ΟFFE2h. Ο επόμενος κωδικός περιμένει μέχρι ο εκτυπωτής να είναι έτοιμος να δεχθεί ένα byte δεδομένων και μετά γράφει το byte στο L.O. byte του ax στην θύρα του εκτυπωτή :

0000:mov bx,[FFE2]
0003:and bx,1
0006:cmp bx,0
0009:je 0000
000c:mov [FFEO],ax

Η πρώτη εντολή τοποθετεί τα δεδομένα στην θύρα κατάστασης εισόδου. Η δεύτερη εντολή λογικά προσθέτει σ’ αυτή την τιμή το 1 για να καθορίσει τα bits 1 ως 15 και βάζει bit 0 στην τρέχουσα κατάσταση της θύρας του εκτυπωτή. Σημειώστε ότι αυτό παράγει μια μηδενική τιμή στο bx, αν ο εκτυπωτής είναι απασχολημένος και τιμή 1 στο bx, αν ο εκτυπωτής είναι σε θέση να δεχθεί επιπρόσθετα δεδομένα. Η τρίτη εντολή τσεκάρει το bx και βλέπει αν περιέχει 0. Αν ο εκτυπωτής είναι απασχολημένος, το πρόγραμμα μεταπηδάει στην τιμή 0 και επαναλαμβάνει την διαδικασία ξανά και ξανά εως ότου το bit του εκτυπωτή γίνει 1.

Ο επόμενος κώδικας παρέχει ένα παράδειγμα για διάβασμα του πληκτρολογίου. Προϋποθέτει ότι το bit κατάστασης είναι bit το 0 της διεύθυνσης OFFE6h (0 σημαίνει ότι κανένα πλήκτρο δεν έχει πιεστεί) και ο κώδικας ASCII του πλήκτρου, παρουσιάζεται στην διεύθυνση OFFE4h όταν το bit 0 της θέσης OFFE6h περιέχει ενα :
 

0000:   mov     bx, [FFE6]
0003:   and     bx, 1
0006:   cmp     bx, 0
0009:   je      0000
000C:   mov     ax, [FFE4]
         .       .
         .       .
         .       .
Αυτός ο τύπος διαδικασίας Εισόδου/ Εξόδου, όπου η CPU συνεχώς  ελέγχει μια θύρα για να εξακριβώσει αν τα δεδομένα είναι διαθέσιμα, κάνει το εξής : η CPU ρωτάει την θύρα αν έχει διαθέσιμα δεδομένα ή αν είναι ικανή να δεχθεί δεδομένα. Η Ε/Ε με σφυγμομέτρηση είναι εξ’ ορισμού αναποτελεσματική. Σκέψου τι συνέβαινε στο προηγούμενο τμήμα κώδικα, αν ο χρήστης έπαιρνε 10 δευτερόλεπτα για να τυπώσει ένα πλήκτρο στο πληκτρολόγιο - η CPU παγιδεύεται σ’ ένα loop μη κάνοντας τίποτα, αυτά τα 10 δευτερόλεπτα.

Η λύση σ’ αυτό το πρόβλημα είναι να παρέχεις ένα μηχανισμό διακοπών (interrupts). Μια διακοπή είναι ένα εξωτερικό γεγονός του hardware που προκαλεί στην CPU να διακόψει την τρέχουσα σειρά εντολών και καλεί μια ειδική ρουτίνα εξυπηρέτησης διακοπών (ISR). Μια ISR τυπικά σώζει όλους τους καταχωρητές και τις σημαίες, κάνει οποιαδήποτε διαδικασία είναι απαραίτητη για να χειριστεί την διακοπή, αποθηκεύει τους καταχωρητές και τις σημαίες και μετά ξαναρχίζει από τον κώδικα στον οποίο διακόπηκε.

Οι CPUS που υποστηρίζουν interrupts πρέπει να παρέχουν κάποιο μηχανισμό που να επιτρέπει στον προγραμματιστή να εξακριβώσει την διεύθυνση του ISR για να εκτελεστεί, όταν συμβαίνει διακοπή. Τυπικά, ένας άνυσμα διακοπής είναι μια ειδική θέση μνήμης, όπου κρατείται η διεύθυνση του ISR . Η CPU x86, για παράδειγμα, περιέχει δυο φορείς διακοπής : έναν για γενικού σκοπού διακοπή και ένα για διακοπή επανεκκίνησης (μηδενισμού).

Αφού ένα ISR ολοκληρώνει τις αρμοδιότητες του, επιστρέφοντας γενικά έναν έλεγχο στην προσκηνιακή εργασία με μια ειδική εντολή return from interrupt (iret). Ένα ISR θα πρέπει να τελειώνει με αυτή την εντολή.
 

3.4. I/O   Είσοδος/Έξοδος.
3.5. Διακοπές και Ε/Ε με σφυγμομέτρηση.

Art of Assembly: Κεφαλαιο 3  - 26 SEP 1996

[Chapter Three][Previous][Chapter Four] [Art of Assembly][Randall Hyde]