Dr.Paneas Δημοσιεύτηκε Ιανουάριος 26, 2010 #1 Κοινοποίηση Δημοσιεύτηκε Ιανουάριος 26, 2010 Η ΟΡΓΑΝΩΣΗ ΜΝΗΜΗΣ ΚΑΙ ΟΙ ΤΡΟΠΟΙ ΠΡΟΣΠΕΛΑΣΗΣ Σύντομη θεωρητική εισαγωγή Τι είναι ο 8051 Ο 8051 είναι ένας μικροεπεξεργαστής ( microprocessor – μC) αναπτυγμένος σε ένα chip ( one chip microcomputer) των 40 pins, κατασκευασμένος από την γνωστή εταιρία επεξεργαστών Intel, περίπου το 1980. Σκοπός του ήταν και είναι η χρήση του σε ενσωματωμένα συστήματα ( αυτά που λέμε embedded systems) όπως είναι ηλεκτρονικά κυκλώματα, αυτοματισμοί, ηλεκτρονικά εμπορικά προϊόντα όπως ψηφιακές φωτογραφικές μηχανές έως παιχνίδια, ηλεκτρικές συσκευές και κάθε είδους αυτοκινούμενα τροχοφόρα οχήματα κλπ. Ο χρήστης/προγραμματιστής χρησιμοποιεί τον 8051 για να του εγγράψει κάποια στιγμή στη μνήμη EPROM (εσωτερική ή εξωτερική) ένα πρόγραμμα που θα τρέχει συνεχώς (ατέρμον βρόχος) ώστε αυτός να κάνει συνέχεια μια συγκεκριμένη δουλειά. πχ να ελέγχει την λειτουργία ενός πλυντηρίου. Το πρόγραμμα που τρέχει ο 8051 είναι γραμμένο στη γλώσσα μηχανής του ως μία σειρά/διαδοχή από bytes που αποτελούν κωδικοποιημένη μορφή εντολών. Η γλώσσα μηχανής του 8051 γράφεται με ένα, δύο ή τρία bytes. Μία εντολή μπορεί να κάνει διάφορες στοιχειώδεις λειτουργίες σε δεδομένα που βρίσκονται στη μνήμη RAM, σε Registers, ή στις Ports του 8051. Για παράδειγμα η εντολή : MOV A,R7λέει βάλε (αντέγραψε) το περιεχόμενο του καταχωρητή ομάδας R7 της ενεργής ομάδας στον συσσωρευτή A . Αυτή η εντολή κωδικοποιείται με το byte E8h που έχει διεύθυνση 29h . Αυτή η εντολή στη γλώσσα μηχανής γράφεται με δύο bytes, τα 25H και 28H. Δεδομένου ότι η γλώσσα του 8051 έχει 255 τέτοιες εντολές καταλαβαίνετε πόσο δύσκολο και επίπονο θα ήταν να γράφουμε προγράμματα γλώσσας μηχανής χρησιμοποιώντας απευθείας τα bytes που κωδικοποιούν τις εντολές. Γι αυτό χρησιμοποιούμε την συμβολική γλώσσα Assembly είτε κάποια γλώσσα χαμηλού/μεσαίου επιπέδου όπως η C . Ο 8051 ήταν πολύ δημοφιλής μέχρι και την δεκαετία του 90’, αλλά σήμερα έχει εμφανώς ξεπεραστεί εξαιτίας της μεγάλης ανάπτυξης καινούριων επεξεργαστών από διάφορες εταιρίες. Για παράδειγμα προτείνεται από πολλούς η χρήση του AVR καθώς είναι φθηνότερος και υπάρχει άφθονο υλικό πηγών στο internet γι αυτόν. Η πρώτη υλοποίηση του 8051 έγινε με την τεχνολογία NMOS και αργότερα εξελίχθηκε στα CMOS η οποία αναγνωρίζεται στο stepping από τα τσιπάκια με το γράμμα “C” στο όνομά τους ( πχ 80C51). Ο λόγος που χρησιμοποιήθηκε η CMOS είναι γιατί απαιτεί λιγότερη ενέργεια, κάτι που έκανε τους μικροεπεξεργαστές αυτούς να είναι συμβατοί με συσκευές που χρησιμοποιούν μπαταρίες. Όπως για παράδειγμα στην motherboard, μετά από ένα αποτυχημένο overclocking, κάνουμε το λεγόμενο "Clear CMOS" το οποίο στην ουσία είναι να αφαιρούμε την μπαταρία από το κύκλωμα. (είτε κυριολεκτικά είτε με ένα jumper βραχυκλώνουμε με την γείωση). Αυτό έχει ως συνέπεια να σταματήσει να τρέχει ένα κύκλωμα μικροελεγκτή που είναι για την συγκεκριμένη δουλειά. Στην ουσία, έτσι κάνουμε reset το BIOS. Αντίθετα, όταν περνάμε μία νέα έκδοση BIOS, στην ουσία το επαναπρογραμματίζουμε, δηλαδή το φλασάρουμε. Στην πραγματικότητα ο 8051 είναι ένας μικροελεγκτής ( microcontroller ) γιατί είναι σχεδιασμένος για γρήγορο και εκτεταμένο χειρισμό σημάτων από και προς ελεγχόμενες από αυτόν εξωτερικές συσκευές. O μικροελεγκτής είναι ένας τύπος επεξεργαστή, ή αν θέλετε μία παραλλαγή μικροεπεξεργαστή ο οποίος μπορεί να λειτουργήσει με εξωτερικά εξαρτήματα, λόγω των πολλών ενσωματωμένων υποσυστημάτων που διαθέτει. Η Αρχιτεκτονική του 8051 Η βασική αρχιτεκτονική των μικροελεγκτών δεν διαφέρει από την κοινή των μικροεπεξεργαστών την αρχιτεκτονική μνήμης τύπου Harvard. Αυτή είναι μια αρχιτεκτονική που λέει ότι ο χώρος διευθύνσεων προγράμματος (ROM) είναι ανεξάρτητος από εκείνων των χώρο διευθύνσεων των δεδομένων ( RAM). Το μήκος των λέξεων στο χώρο του προγράμματος μπορεί να διαφορετικό από το μήκος των λέξεων στο χώρο των δεδομένων. Οι εντολές στα προγράμματα μπορούν να έχουν σαν ορίσματα τις διευθύνσεις του χώρου των δεδομένων ( βλ pointers). Σ’ αυτήν την αρχιτεκτονική βασίζεται ο 8051, δηλαδή έχει ξεχωριστό χώρο διευθύνσεων για το πρόγραμμα και τα δεδομένα. Παρόλα αυτά με έναν κατάλληλο συνδυασμό των pins !PSEN και !RD μπορεί να αλλάξει η αρχιτεκτονική σε von Neuman, όπου πλέον εκεί αναφερόμαστε σε ένα ενιαίο χώρο διευθύνσεων χωρίς να ξεχωρίζουμε δεδομένα και πρόγραμμα. Τι είναι μικροεπεξεργαστής Ο 8051 αποτελείται από τον μικροεπεξεργαστή και άλλα υποσυστήματα. Ο μικροεπεξεργαστής αποτελείται από την μονάδα επεξεργασίας δεδομένωνμονάδα ελέγχου. και την Ένας σύγχρονος μικροεπεξεργαστής αποτελείται από τις ακόλουθες μονάδες. Μονάδα αποκωδικοποίησης (Decoding Unit) Λογική και Αριθμητική Μονάδα (Arithmetic and Logical Unit, ALU): Η μονάδα στην οποία εκτελούνται μία προς μία οι αριθμητικές ή λογικές πράξεις, όπως υπαγορεύονται από τις εντολές που έχουν δοθεί στον υπολογιστή. Καταχωρητές (Registers): Μικρά κύτταρα μνήμης στο εσωτερικό του επεξεργαστή, που χρησιμοποιούνται για την προσωρινή αποθήκευση των δεδομένων, καθώς αυτά υφίστανται επεξεργασία. Οι καταχωρητές διαφέρουν ανάλογα με τον τύπο του επεξεργαστή και τον κατασκευαστή, τόσο ως προς την οργάνωση όσο και ως προς τη χωρητικότητά τους. Μονάδα ελέγχου (Control Unit): Ελέγχει τη ροή δεδομένων από και προς την ALU, τους καταχωρητές, τη μνήμη και τις περιφερειακές μονάδες εισόδου/εξόδου. Μονάδα προσκόμισης (Fetch Unit): Μεταφέρει τις εντολές από τη μνήμη στον επεξεργαστή. Μονάδα προστασίας (Protection Unit): Εξασφαλίζει το αποδεκτό σφάλμα της κάθε διεργασίας που εκτελεί ο επεξεργαστής, ώστε να μη τροποποιούνται δεδομένα που δεν πρέπει ή να μην εκτελούνται μη αποδεκτές εντολές, όπως, π.χ., διαίρεση αριθμού με το μηδέν. Βλέπετε το block διάγραμμα μικροεπεξεργαστή [ATTACH]7067[/ATTACH] Τι είναι μικροελεγκτής Όπως προείπαμε ο 8051 είναι μικροελεγκτής, για αυτό αποτελείται απ’ όλα τα παραπάνω (όντας μικροεπεξεργαστής) και από κάποια άλλα υποσυστήματα. Αυτά είναι η μνήμη δεδομένων RAM ( Random Access Memory ) για την προσωρινή αποθήκευση δεδομένων, και η μνήμη προγράμματος ROM (Read Only Memory) ή EPROM ή EEPROM για την μόνιμη αποθήκευση του προγράμματος. Για επικοινωνία με τον έξω κόσμο διαθέτει τέσσερις παράλληλες πόρτες των 8 bits (P0, P1, P2, P3 ) καθώς και σειριακή θύρα ( UART). Τα εσωτερικά στοιχεία του 8051 συνδέονται μεταξύ του με τον εσωτερικό δίαυλο δεδομένων (εσωτερικό data bus), τον εσωτερικό δίαυλο διευθύνσεων ( address bus ) και τον εσωτερικό δίαυλο ελέγχου ( control bus ). Σε περίπτωση όπου δεν επαρκούν οι εσωτερικές/ενσωματωμένες (on-chip) RAM και ROM μνήμες, ο 8051 έχει την δυνατότητα σύνδεσης με εξωτερικές. Κατά την εκτέλεση των εντολών ενός προγράμματος ο μικροελεγκτής μεταβαίνει από κατάσταση σε κατάσταση στα αρνητικά μέτωπα της παλμοσειράς του clock. Η συνήθης συχνότητα ρολογιού για τον 8051 είναι 12Mhz, όπου 12 παλμοί του ρολογιού συνιστούν έναν κύκλο μηχανής του 8051. Έχει λοιπόν συχνότητα ρολογιού 12 Mhz, περίοδο ρολογιού 1/12μsκαι ο κύκλος μηχανής διαρκεί 1μs. [ATTACH]7068[/ATTACH] Τα σημαντικότερα τεχνικά χαρακτηριστικά του 8051 είναι τα εξής: Παρέχει λειτουργικότητα (CPU, RAM, I/0, λογικούς διακόπτες, Χρονιστή, κρυσταλλικό ταλαντωτή για το ρολόι κλπ ) σε ένα single chip. 8-bit ALU, Accumulator και Registers , γεγονός που επιβεβαιώνει ότι είναι ένας 8-bit microcontroller. 8-bit δίαυλο δεδομένων – μπορεί να έχει πρόσβαση σε 8 bit δεδομένων με μία φορά 16-bit δίαυλο διευθύνσεων – μπορεί να έχει πρόσβαση σε 216 τοποθεσίες μνήμης – δηλαδή 64kiB (65536 τοποθεσίες) για RAM και ROM. Εσωτερική (on-chip) RAM – 128 bytes ή 256 bytes( μνήμη δεδομένων) ανάλογα με το μοντέλο. Εσωτερική (on-chip) ROM – 4kiB (μνήμη προγράμματος). 4 Byte διπλής κατεύθυνσης θύρα I/0 . UART ( Σειριακή θύρα ). Δύο 16-bit Counter/Timers Δύο επίπεδα προτεραιότητας διακόπτη Σχέδιο χαμηλής κατανάλωσης ενέργειας Βλέπετε το Block Διάγραμμα του μικροελεγκτή [ATTACH]7069[/ATTACH] Το εσωτερικό ενός Intel 8051 Microcontroller [ATTACH]7070[/ATTACH] Το pinout του 8051 [ATTACH]7071[/ATTACH] Οργάνωση Μνήμης Οι εντολές που δίνουμε στον 8051 αναφέρονται και τροποποιούν τα περιεχόμενα κάποιων καταχωρητών ή θέσεων μνήμης γραφής και ανάγνωσης του 8051. Εσωτερική Μνήμη RAM – Μνήμη Δεδομένων Η εσωτερική μνήμη RAM του 8051 έχει 128 θέσεις μνήμης των 8bit η κάθε μία ξεχωριστά. Από 0x00 [0] μέχρι 0x7F [127] έχουμε 128 θέσεις 1Byte εσωτερικής μνήμης RAM και από 0x80 [128] μέχρι 0xFF [255] έχουμε 128 μερικές θέσεις που καταλαμβάνουν οι SFR – Special Function Registers ( Καταχωρητές Ειδικής Λειτουργίας ). Οι υπόλοιπες θέσεις μεταξύ 0x80 και 0xFF που δεν καταλαμβάνονται από SFR μένουν αχρησιμοποίητες και δεν είναι διαθέσιμες για αποθήκευση bytes. Με απλά λόγια θα λέγαμε λοιπόν ότι η εσωτερική μνήμη RAM είναι σπασμένη σε δύο κομμάτια. Στο πρώτο κομμάτι έχουμε 128 ( 0 ---> 127 ) θέσεις και στο δεύτερο κομμάτι 127 ( 128 ---> 255 ) θέσεις που είναι είτε SFR, είτε κενές και άχρηστες προς αποθήκευση. Γενικότερα αναφερόμαστε στην εσωτερική RAM ως μία 128bytes μνήμη. Αν αυτή είναι 256bytes τότε το δεύτερο κομμάτι της ταυτίζεται με τους SFR. Μελετώντας πιο προσεχτικά το πρώτο κομμάτι της εσωτερικής RAM βλέπουμε ότι έχουμε 128 θέσεις. Αρχίζουμε από την 00h και τελειώνουμε στην 7Fh . Πρώτο Κομμάτι ( Απευθείας RAM | DirectRAM ) [ 0 – 127 ] Bank Registers [ 0 – 31 ] Στις πρώτες 32 θέσεις ( 0 έως 31 – 00h έως 1Fh ) έχουμε τις 4 ομάδες καταχωρητών ( bank registers ) , οι οποίες είναι Register Bank 0 , 1 , 2 , 3 . Η κάθε ομάδα αποτελείται από 8 καταχωρητές ομάδας ( work registers ) οι οποίοι είναι: R0, R1, R2, R3, R4, R5, R6, R7 . Συνεπώς η πρώτη ομάδα καταχωρητών αρχίζει από την θέση 00h και τελειώνει στην θέση 07h. Η δεύτερη αρχίζει από την θέση 08h και τελειώνει στην θέση 0Fh. Η τρίτη αρχίζει από την θέση 10h και τελειώνει στην 17h. Και η τελευταία και τέταρτη ομάδα αρχίζει από την θέση 18h και τελειώνει στην 1Fh θέση. Bit Addressable [ 32 – 47 ] Στις επόμενες 16 θέσεις ( από την 32 έως 47 -- 20h έως 2Fh ) έχουμε θέσεις μνήμης οι οποίες μπορούν να προσπελαστούν με δική τους 8-bit διεύθυνση ( bit addressable ) . Δηλαδή έχουμε 16 θέσεις μνήμης, όπου στην κάθε θέση μπορούμε να βάλουμε μέχρι 8bit και να έχουμε πρόσβαση σ'αυτά ξεχωριστά. πχ πρόσβαση στο 2ο bit της θέσης μνήμης 21h , είναι μία έγκυρη εντολή. Αντίθετα πρόσβαση στο 2ο bit της θέσης μνήμης 81h είναι άκυρη εντολή, επειδή η συγκεκριμένη θέση ΔΕΝ είναι προσπελάσιμη κατά bit. Γενικής Χρήσης [ 47 – 127 ] Όπως είπαμε νωρίτερα το πρώτο μέρος της εσωτερικής RAM μνήμης δεδομένων αποτελείται από 128 θέσεις μνήμης και εμείς έχουμε μιλήσει για το τι βρίσκεται στις 32+16 = 48 πρώτες θέσεις της. Οι υπόλοιπες 80 θέσεις που μένουν είναι θέσεις γενικού σκοπού για οποιαδήποτε αποθήκευση. Αυτές οι 80 θέσεις αρχίζουν από την θέση 30h και τελειώνουν στην 7Fh , όπου τελειώνει και το πρώτο κομμάτι της εσωτερικής RAM. Βλέπετε μία απεικόνιση του πρώτου κομματιού της εσωτερικής RAM . [ATTACH]7072[/ATTACH] Δεύτερο Κομμάτι ( Έμμεση RAM | IndirectRAM ) [ 128 – 255 ] Στην συνέχεια, στο δεύτερο κομμάτι της RAM βλέπουμε αχρησιμοποίητες θέσεις μνήμης που δεν μπορούμε να γράψουμε δεδομένα, και τους καταχωρητές ειδικής λειτουργίας SFR ( Special Function Registers ). Το κομμάτι αυτό, όπως προείπαμε, αρχίζει από την θέση 80h και τελειώνει στην FFh. Βλέπετε τις 128 θέσεις του δεύτερο πάνω μισού της εσωτερικής RAM. [ATTACH]7073[/ATTACH] Ορίστε μία απεικόνιση ολόκληρης της εσωτερική μνήμης RAM μαζί με το δεύτερο κομμάτι των SFR . [ATTACH]7074[/ATTACH] Μνήμη ROM – Μνήμη Προγράμματος ( Εσωτερική και Εξωτερική ) Αρκετά είπαμε όμως για την εσωτερική μνήμη RAM. Ας περάσουμε στην εσωτερική μνήμη ROM, την μνήμη προγράμματος ( code memory ) , όπου διατηρείται ο κώδικας του προγράμματος μας. Γενικότερα για εξωτερική και εσωτερική ROM , ο 8051 χρησιμοποιεί 16bit διευθύνσεις . Δηλαδή μπορεί να προσπελάσει 64k. Ενώ για εσωτερική RAM έχει 8bit διευθύνσεις. Το μέγεθος της εσωτερικής ROM είναι 4kiB και εκεί φυλάσσετε ο κώδικας, δηλαδή η μνήμη του προγράμματος . Η εξωτερική ROM έχει μέγεθος 60k. Συνεπώς εξωτερική ROM + εσωτερική ROM = 64k χωρίς αυτό να είναι αναγκαίο. Υπάρχουν διάφοροι συνδυασμοί όπου μπορεί να μην έχουμε καθόλου εσωτερική ROM και να έχουμε όλα τα 64k στην εξωτερική ROM. Η εξωτερική RAM έχει μέγεθος 64k. Τύπος Μνήμης Εσωτερική RAM : 128 bytes( ο κλασσικός 8051) 256 bytes ( 256 + 128 SFR ) Εσωτερική ROM 4kiB Εξωτερική RAM 64kiB Εξωτερική ROM 60kiB Παρακάτω βλέπετε μία συνολική εικόνα των μνημών: [ATTACH]7075[/ATTACH] Στην περίπτωση όπου έχουμε εσωτερική RAM 256 bytes τότε το δεύτερο κομμάτι της RAM έχει τις ίδιες διευθύνσεις με τους SFR και διαφέρει στον τρόπο προσπέλασής του. Βλέπετε μία πιο λεπτομερής εικόνα των μνημών [ATTACH]7076[/ATTACH] ΤΡΟΠΟΙ ΠΡΟΣΠΕΛΑΣΗΣ ΜΝΗΜΗΣ Αυτό που πρέπει να γίνει πρώτα είναι να ερμηνευθούν τα σύμβολα: Codememory Μνήμη προγράμματος. C Direct addressable internal RAM = Εσωτερικήαπευθείαςπροσπελάσιμη RAM. D Indirect addressable internal RAM = ΕσωτερικήέμμεσαπροσπελάσιμηRAM. I External memory = Εξωτερικήμνήμη. X Bit addressable RAM = Προσπελάσιμηκατά bit RAM. B Peripheralmemory = Περιφερειακή μνήμη (ακροδέκτες θυρών εισόδου / εξόδου) P Πειραματική διαδικασία ΑΣΚΗΣΗ 2.1 Ανοίξτε το debugger και δώστε στο παράθυρο Memory την εντολή d D:0000h. Θα εμφανιστούν τα περιεχόμενα των θέσεων της απ’ ευθείας (Direct) προσπελάσιμης μνήμης. Επαληθεύστε τις τιμές Reset, συγκρίνοντας με αυτές που εμφανίζει ο Πίνακας 2-1. Ανοίγοντας το MemoryWindowγράφοντας την εντολή D:0000hβλέπω τις θέσεις RAMαπό 0000hέως 7Fh. Οι τιμές που επαληθεύονται είναι οι τιμές που βλέπω από 80hμέχρι FFh, οι οποίες υπάρχουν στον πίνακα των SFRτου βιβλίο σελ24. ΑΣΚΗΣΗ 2.2 Δώστε τη διαταγή e I:0010=κωδ1, παρατηρήστε και εξηγήστε το αποτέλεσμα της. Δίνοντας αυτήν την εντολή μιλάμε απευθείας στον compilerόπου του λέμε να δώσει στην θέση εσωτερικής μνήμης έμμεσης RAMτον κωδ1 ο οποίος είναι ένα νούμερο (σταθερά). Δηλαδή Για παράδειγμα δίνοντας eD:00E0h = 2 όπου είναι η διεύθυνση του ACCβλέπουμε ότι όντως παίρνει αυτή την τιμή. [ATTACH]7077[/ATTACH] ΑΣΚΗΣΗ 2.3 Δώστε τις διαταγές Α=κωδ2, Β=κωδ2+1, R0= κωδ2+2, R1= κωδ2+3,…,R7= κωδ2+9, DPTR=8000h, SP= κωδ2+10, CY=1 και ΟV=1 και επαληθεύστε τα αποτελέσματα τους στο παράθυρο Registers και στο παράθυρο Memory. Παρατηρούμε ότι όντως όλες οι εντολές έχουν εκτελεστεί και έχουν εφαρμοστεί στους καταχωρητές. Αξίζει να σημειωθεί ότι ο DataPoiTeRRegistersσπάει σε 2 θέσεις μνήμης . Στην 82h όπου κρατάει το lowbit <εισέρχεται το 00 > Στην 83h όπου κρατάει το highbit <εισέρχεται το 80> ΑΣΚΗΣΗ 2.4 Φορτώστε το πρόγραμμα EX1-1 και επαληθεύστε τον κώδικα όπως περιέχεται στην μνήμη, με αυτόν που παρήγαγε ο μεταφραστής και περιέχεται στο αρχείο EX1-1.lst. Ανοίγουμε το αρχείο *.LST και βλέπουμε τον κώδικα. Στην συνέχεια ανοίγουμε να δούμε την ROM με την εντολή C:διεύθυνση όπου εκεί βλέπουμε τον ίδιο κώδικα με εντολές. [ATTACH]7078[/ATTACH] Link to comment Share on other sites More sharing options...
Dr.Paneas Ιανουάριος 26, 2010 Author #2 Κοινοποίηση Ιανουάριος 26, 2010 ΑΣΚΗΣΗ 2.5 Το επόμενο πρόγραμμα πόλλαπλασιάζει τους αριθμούς 30h και 8Ch. Γράφει το αποτέλεσμα στη θέση VAR1. Γράψτε, μεταφράστε και εκτελέστε το πρόγραμμα, επαληθεύοντας η λειτουργία του. ; Πρόγραμμα πολλαπλασιασμού δύο σταθερών αριθμών ; Όνομα : ………… ; VAR1 equ 40h ; cseg at 0 MOVA,#3 ;Βάλε τον 3 αριθμό στον Α MOVB,#2 ;Βάλε τον 2 αριθμό στον B MUL AB ;Πολλαπλασίασε Α επι Β MOV VAR1,B ; Φύλαξε το αποτέλεσμα, πρώτα το highbyte MOV VAR1+1,A ; καιμετάτο low byte HALT: JMP HALT end To ; ( semicolon ) χρησιμοποιείται για την εισαγωγή σχολίου, καθώς μπορεί να χρησιμοποιηθεί και ο κλασσικό τύπος commenting της C /* . . . */ Όπου βλέπει ο Assembler VAR1 την εξισώνει ( equals ) με την θέση 40h . Αρχικά ο ACC έχει την τιμή 00003 και ο Β την τιμή 0002. Μετά τον πολλαπλασιασμό τους, το αποτέλεσμα αποθηκεύεται στον ACC ο οποίος παίρνει την τιμή 0006. Μετά αποθηκεύει στην θέση 40h το HIGH Byte δηλαδή το 00 και στην συνέχεια το Low Byte που είναι το 06 στην θέση 41h. [ATTACH]7079[/ATTACH] Συμπεράσματα Γνωρίζουμε πλέον την δομή μνήμης του 8051. Τι ιδιαιτερότητες και τι προτερήματα έχει, το μέγεθός της, τις διευθύνσεις της, αλλά και πώς μπορούμε να προσπελάσουμε αυτές τις διευθύνσεις. Όλα αυτά έγιναν πράξη με το μVisionόπου μέσω του debuggin είδαμε βήμα-βήμα την λειτουργία των εντολών μέσα στην μνήμη του 8051 ( χρησιμοποιώντας το Memory Window ). Link to comment Share on other sites More sharing options...
Dr.Paneas Ιανουάριος 26, 2010 Author #3 Κοινοποίηση Ιανουάριος 26, 2010 ΤΡΟΠΟΙ ΔΙΕΥΘΥΝΣΙΟΔΟΤΗΤΗΣ – ΕΝΤΟΛΕΣ ΜΕΤΑΦΟΡΑΣ ΔΕΔΟΜΕΝΩΝ Σύντομη θεωρητική εισαγωγή ΤΡΟΠΟΙ ΠΡΟΣΠΕΛΑΣΗΣ ΜΝΗΜΗΣ Αυτό που πρέπει να γίνει πρώτα είναι να ερμηνευθούν τα σύμβολα: C Codememory = Μνήμη προγράμματος. D Direct addressable internal RAM = Εσωτερικήαπευθείαςπροσπελάσιμη RAM. I Indirect addressable internal RAM = ΕσωτερικήέμμεσαπροσπελάσιμηRAM. X External memory = Εξωτερικήμνήμη. B Bit addressable RAM = Προσπελάσιμηκατά bit RAM. P Peripheralmemory = Περιφερειακή μνήμη (ακροδέκτες θυρών εισόδου / εξόδου). Οι εντολές για την προσπέλαση μνήμης είναι: [ATTACH]7080[/ATTACH] Έχουμε 6 τρόπους addressing. Επειδή η ελληνική μετάφραση δεν αντιστοιχεί ακριβώς στην ακριβή ορολογία θα χρησιμοποιήσω μόνο την αγγλική. Immediate Addressing Όπως φαίνεται και από το όνομα, Immediate addressing λέγεται η διευθυνσιοδότηση όπου η τιμή που θα αποθηκευτεί στην μνήμη ακολουθείται απευθείας (immediately) από τον «κωδικό λειτουργίας / operation code» στην μνήμη. Η ίδια εντολή υποδεικνύει την τιμή που θα αποθηκευτεί στην μνήμη. Δηλαδή τα δεδομένα είναι μέρος της ίδιας της εντολής. Για παράδειγμα, η οδηγία: [SIZE=2] MOV A,#20h [/SIZE] Αυτή η οδηγία χρησιμοποιεί Immediate Addressing επειδή ο Accumulator θα φορτωθεί με την τιμή που ακολουθεί αμέσως μετά. Στην περίπτωσή μας το 20 (hex) . Η Immediate Addressing είναι πολύ γρήγορη και αυτό γιατί η τιμή που πρόκειται να φορτωθεί στην μνήμη περιλαμβάνεται στην ίδια την οδηγία/εντολή. Παρόλα αυτά, επειδή η τιμή που θα φορτωθεί φτιάχνεται κατά τον χρόνο μετάφρασης, δεν είναι και πολύ ευέλικτη εντολή. Αξίζει να σημειωθεί ότι αν θέλουμε να φορτώσουμε hex που αρχίζει από γράμμα, τότε πρέπει να βάλουμε μπροστά του ένα μηδενικό πχ MOV A,#0Eh αντί για MOX A,#Eh που είναι λάθος Ας δούμε μερικές εντολές: MOV A,#12h Βάλε στον Accumulator την σταθερά 12 (hex) MOV R7,#12h Βάλε στον καταχωρητή ομάδας R7 την σταθερά 12 (hex) MOV DPH,#12h Βάλε στο High Byte του DTPR την σταθερά 12 (hex) MOV DPL,#12h Βάλε στο Low Byte του DPTR την σταθερά 12 (hex) MOV DPTR,#12h Βάλε στον DTPR την σταθερά 12 (hex) MOV @R0,#12h Βάλε στην μνήμη που δείχνει ο R0 την τιμή 12 (hex) MOV 35h,#12h Βάλε στην διεύθυνση 35 (hex) της μνήμης, την σταθερά 12 (hex). Με αυτόν τον τρόπο αναφερόμαστε σε τιμή. Για παράδειγμα θα ήταν λάθος να γράψουμε MOV 12h,#R7 γιατί ο R7 είναι καταχωρητής και όχι τιμή. Direct Addressing Direct Addressing λέγεται η διευθυνσιοδότηση όπου η τιμή που θα αποθηκευτεί στην μνήμη προέρχεται άμεσα (directly) από μία άλλη θέση της μνήμης. Με τον τρόπο αυτόν μπορούμε να κάνουμε προσπέλαση στα κάτω 128 bytes της RAM και στους SFR. Αν η RAM είναι 256 bytes τότε στα πάνω 128bytes που συμπίπτουν με τις διευθύνσεις των SFR δεν μπορούμε να προσπελάσουμε με αυτόν τον τρόπο. Για παράδειγμα: MOV A,30h [SIZE=2]Αυτή η οδηγία, θα διαβάσει τα δεδομένα από την εσωτερική RAM που βρίσκονται στην θέση 30 (hex) και θα την αποθηκεύσει στον Accumulator. [/SIZE] [SIZE=2][/SIZE] Αυτός ο τρόπος δίνει πιο αργές εντολές σε σχέση με την Immediate Addressing, αλλά επειδή η πληροφορία ανταλλάσσεται εσωτερικά στην RAM, η λειτουργία παραμένει αρκετά γρήγορη. Επίσης είναι πιο ευέλικτη αφού η τιμή που θα φορτωθεί είναι ότι υπάρχει ήδη στην διεύθυνση μνήμης – η οποία μπορεί να διαφέρει ( σε σχέση με πριν που μπορούσαμε να φορτώσουμε μία συγκεκριμένη τιμή). Αυτό που αξίζει να πούμε για μία ακόμα φορά είναι ότι με Direct Addressing μπορούμε να κάνουμε προσπέλαση τα κάτω 128bytes της εσωτερικής RAM. Δηλαδή τις διευθύνσεις από 00 έως 7Fh. Επίσης μπορούμε να προσπελάσουμε και τους SFR, δηλαδή τις διευθύνσεις 80h μέχρι FFh. Σε περίπτωση όμως που η εσωτερική RAM είναι 256kB τότε όπως είπαμε αρκετά πιο πάνω, έχουμε δύο διαφορετικά τμήματα στο πάνω μέρος της RAM. Δηλαδή έχουμε: 1) Τμήμα: Από 80h μέχρι FFh που είναι SFR και άχρηστες κενές θέσεις μη χρησιμοποιούμενες. 2) Τμήμα: Από 80h μέχρι FFh που είναι η συνέχεια της απλής γενικής χρήσης RAM. Για παράδειγμα στην θέση μνήμης 0E0h βρίσκεται ο ACC ο οποίος είναι ένας SFR. Μπορώ να τον προσπελάσω με Direct Addressing. [SIZE=2]πχ MOV A,h30 // βάλε στον Α ότι υπάρχει στην θεση 30hή με την διεύθυνση του: MOV 0E0h, h30 η παραπάνω εντολή θα αποθηκεύση την τιμή της θέσης μνήμης 30h στον Accumulator που είναι SFR και όχι στην θέση μνήμης γενικού σκοπού 0E0h. Γιατι ; Γιατί χρησιμοποιήσαμε Direct Addressing που αυτό σημαίνει ότι μπορείς να γράφεις είτε στο κάτω μισό της εσωτερικής RAM είτε στο πάνω μισό ΑΛΛΑ ΜΟΝΟ στο τμήμα των SFR. [/SIZE] Ας δούμε μερικές εντολές: MOV A,12h Βάλε στον Accumulator το περιεχόμενο της μνήμης RAM με διεύθυνση 12 (hex) MOV R7,12h Βάλε στον καταχωρητή ομάδας R7 το περιεχόμενο της μνήμης RAM με διεύθυνση 12 (hex) MOV 12h,R7 Βάλε στην διεύθυνση 12 (hex) της μνήμης RAM, την τιμή που βρίσκεται στην διεύθυνση του καταχωρητή R7. Δηλαδή την τιμή που κρατάει ο R7. MOV DPH,#12h Βάλε στο High Byte του DTPR την σταθερά 12 (hex) MOV DPL,12h Βάλε στο Low Byte του DPTR το περιεχόμενο της μνήμης RAM με διεύθυνση 12 (hex) MOV DPTR,12h Βάλε στον DTPR το περιεχόμενο της μνήμης RAM με διεύθυνση 12(hex) MOV @R0, 12h Βάλε στην μνήμη που δείχνει ο R0, το περιεχόμενο της μνήμης RAM με διεύθυνση 12 (hex) MOV 35h,12h Βάλε στην διεύθυνση 35 (hex) της μνήμης, το περιεχόμενο της μνήμης RAM με διεύθυνση 12 (hex). XCH A,12h Αντάλλαξε δεδομένα PUSH 12h Βάλε στην στοίβα το περιεχόμενο της μνήμης RAM με διεύθυνση 12 hex POP 12h Βγάλε από την στοίβα το περιεχόμενο της μνήμης RAM με διεύθυνση 12 hex Σ’ αυτή την κατηγορία εντάσσεται και το Register Addressing. Για παράδειγμα: [SIZE=2] MOV A,R0[/SIZE] Βάλε στον A, αυτό που κρατάει ο register R0. Μπορεί να γίνει επίσης και το ανάποδο, δηλαδή να βάλουμε στον R0, αυτό που κρατάει ο Accumulator. Προσέξτε όμως κάτι που είναι πολύ σημαντικό. Δεν μπορούμε να έχουμε : MOV R0,R2 Καθώς αυτό απαγορεύεται να γίνει στον 8051 ως εντολή. Για αυτό μπορούμε να χρησιμοποιήσουμε την επόμενη μέθοδο, Indirect Addressing. Indirect Addressing Αυτός ο τρόπος είναι πολύ ισχυρός και μας παρέχει επιπλέον ευελιξία. Αποτελεί τον μοναδικό τρόπο προσπέλασης των επιπλέον 128bytes της εσωτερικής RAM (αν αυτή είναι 256bytes) σε έναν 8051 microcontroller. Για παράδειγμα MOV A,@R0 Αυτή η οδηγία κάνει τον 8051 να αναλύσει την τιμή του R0 register. Στην συνέχεια, ο 8051 θα φορτώσει στον Accumulator μια τιμή από την εσωτερική RAM της οποίας η διεύθυνση είναι η τιμή που δείχνει ο R0. Για παράδειγμα, ας πούμε ότι ο R0 κρατάει την τιμή 40h και στην διεύθυνση 40h της εσωτερικής RAM υπάρχει αποθηκευμένη η τιμή 67h. Τότε, όταν εκτελεστεί η εντολή στον 8051, αυτός θα ελέγξει πρώτα απ’ όλα την τιμή του R0. Από την στιγμή που ο R0 κρατάει την τιμή 40h, o 8051 θα βάλει την τιμή που βρίσκεται σ’ αυτήν την θέση εσωτερικής μνήμης RAM (δηλαδή την τιμή 67h) και θα την αποθηκεύσει στον Accumulator. Έτσι, το τελικό αποτέλεσμα είναι ο Accumulator να έχει την τιμή 67h. Σημαντικό: Το Indirect Addressing αναφέρεται πάντα στην εσωτερική RAM και ποτέ στους SFR. Η λογική είναι να φορτώνουμε την διεύθυνση που κρατάει τα δεδομένα μας στους registers συνήθως με Immediate Addressing και μετά να περνάμε τον Register με Indirect έτσι ώστε να γίνεται προσπέλαση στην διεύθυνση μνήμης που ορίσαμε στην αρχή. Για παράδειγμα επειδή δεν μπορούμε να κάνουμε : MOV R0,R1 Θα κάνουμε:MOV A,R1 MOV R0,A Ή ένας άλλος τρόπος θα ήταν: MOV A,#01h MOV R0,@A Μερικές εντολές: MOV A,@R0 Βάλε στον A, το περιεχόμενο της μνήμης που δείχνει ο R0. MOV @R0,A Βάλε στην διεύθυνση που δείχνει ο R0, το περιεχόμενο του Α. MOV @R0,12h Βάλε στην διεύθυνση που δείχνει ο R0, το περιεχόμενο της μνήμης στην θέση 12 ( hex) MOV 12h,@R0 Βάλε στην θέση 12 (hex) της μνήμης, το περιεχόμενο της μνήμης στην διεύθυνση που δείχνει ο R0. External Direct Addressing Είναι ο direct τρόπος για να γράψουμε κάτι στην 2Byte ( 16bit ) εξωτερική RAM. Το σκεπτικό είναι το εξής: Αρχικά φορτώνουμε στον DPTR την εξωτερική διεύθυνση μνήμης που θέλουμε γράψουμε: πχ MOV DPTR,#15h Έτσι φορτώνω στον DTPR την διεύθυνση 15h της εξωτερικής μνήμης. READ from External RAM Στην συνέχεια η επόμενη εντολή θα αντιγράψει δεδομένα από την εξωτερική διεύθυνση στον Accumulator: MOVX A,@DPTR Κατά αυτόν τον τρόπο διαβάζουμε δεδομένα από την εξωτερική μνήμη. WRITE to External RAM Για να γράψουμε δεδομένα, τότε γράφουμε: MOVX @DPTR,A Αυτή η εντολή γράφει στην εξωτερική διεύθυνση μνήμης που δείχνει ο DPTR, την τιμή που κρατάει ο Accumulator. External Indirect Addressing Αυτός ο τρόπος δεν συνηθίζεται και είναι χρήσιμος όταν θέλουμε να μεταφέρουμε στην εξωτερική μνήμη μικρά δεδομένα (όπου δεν έχει nibbles για να χωρίσουμε σε High Byte και Low Byte ώστε να μην υπάρχει ανάγκη χρήσης του DPTR 16bit register). Για αυτό τον λόγο φορτώνουμε στον R0 την διεύθυνση της εξωτερικής μνήμης που θέλουμε αποθηκεύσουμε τα δεδομένα μας (περίπτωση WRITE) . Οπότε γράφουμε: MOVX @R0,A Πειραματική διαδικασία ΑΣΚΗΣΗ 3.1 Αντιγράψτε το περιεχόμενο της θέσης κωδ1 στην εσωτερική μνήμη RAMστον καταχωρητή R4 χρησιμοποιώντας διευθυνσιοδότηση. a. Register – Direct b. Direct – Direct c. Indirect στην κωδ1 d. Indirect στον R4 [SIZE=2] a) MOV R4,κωδ1h MOV 04h,κωδ1h c) MOV R0,#κωδ1 MOV R4,@R0 d) MOV @R4,κωδ1[/SIZE] Ανοίγοντας το MemoryWindowγράφοντας την εντολή D:0000hβλέπω τις θέσεις RAMαπό 0000hέως 7Fh. Οι τιμές που επαληθεύονται είναι οι τιμές που βλέπω από 80hμέχρι FFh, οι οποίες υπάρχουν στον πίνακα των SFRτου βιβλίο σελ24. ΑΣΚΗΣΗ 3.2 Γράψτε την σταθερά κωδ2 στις θέσεις μνήμης RAMαπό 20hμέχρι 23hμε διευθυνσιοδότηση: a. Direct – Immediate b. Direct – Direct c. Direct – Register d. Indirect – Indirect MOV A,#12h MOV 20h,A MOV 21h,A MOV 22h,A MOV 23h,A MOV 20h,#12h MOV 21h,#12h MOV 22h,#12h MOV 23h,#12h MOV 15h,#12h MOV R0,#15h MOV 20h,@R0 MOV 21h,@R0 MOV 22h,@R0 MOV 23h,@R0 MOV 15h,#12h XCH A,15h MOV 20h,A MOV 16h,#12h XCH A,16h MOV 21h,A MOV 17h,#12h XCH A,17h MOV 22h,A MOV 18h,#12h XCH A,23h MOV 23h,A ΑΣΚΗΣΗ 3.3 Γράψτε στην εξωτερική μνήμη RAMστη διεύθυνση 0C00h τη σταθερά κωδ1 MOVDPTR,#0C00h ;Βάλε στον DPTR την εξωτερική διεύθυνση X:0x0C00 MOV Α,#κώδ1 ;Βάλε στον A την σταθερά κωδ1 MOV @DPTR,A ;Γράψε τον Α στην εξωτερική διεύθυνση που δείχνει ο DPTR ΑΣΚΗΣΗ 2.4 Γράψτε τη σταθερά κωδ2 στην θέση 0Ε0hτης εσωτερικής RAM (προσοχή: όχι στους SFR). Πρόκειται για τα πάνω 128bytesτης RAM, συνεπώς θα χρησιμοποιήσω IndirectAddressing έτσι ώστε να αποφύγω την εγγραφή στον Accumulatorπου αντιστοιχεί στην διεύθυνση ;μνήμης D:0x0E0hτων SFR MOVR0,#0E0h ;Ο R0 Registerκρατάει την τιμή 0x0E0h MOV @R0,#κωδ2 ;Βάλε στην διεύθυνση που δείχνει ο R0, την σταθερά κωδ2 Για την επαλήθευση δείτε I:0E0h ΠΡΟΧΟΣΗ: Αν δείτε D:0E0hτότε θα δείτε SFRπου είναι λάθος. Συμπεράσματα Γνωρίζουμε πλέον τους τρόπους addressingστην μνήμη του 8051. Πλέον γνωρίζουμε τόσο θεωρητικά την δομή της μνήμης, αλλά πλέον μπορούμε με τις γνώσεις μας να προσπελάσουμε τις θέσεις αυτές και να επαληθεύσουμε αν τελικά καταλάβαμε σωστά την σημερινή έννοια του μαθήματος. Το βασικότερο είναι ότι ξεχωρίσαμε ότι αν η μνήμη RAMείναι 256bytes, τότε τα πάνω 128bytesέχουν ίδιες διευθύνσεις με τους SFR. Για να ξεχωρίσουμε πότε θα απευθύνουμε σε SFRκαι πότε στα 128πάνω της RAM, χρησιμοποιούμε διαφορετικό τρόπο διευθυνσιοδότηση . Επίσης δεν ξεχνάμε ότι δεν υπάρχει Register – Registeraddressingπχ MOVR0,R1 Τέλοςμάθαμετρόπους READ και WRITE απότηνεξωτερική RAM τόσο Indirect όσο Direct Addressing modes. Link to comment Share on other sites More sharing options...
Dr.Paneas Ιανουάριος 26, 2010 Author #4 Κοινοποίηση Ιανουάριος 26, 2010 ΕΝΤΟΛΕΣ ΔΙΑΚΛΑΔΩΣΗΣ Σύντομη θεωρητική εισαγωγή Αυτό που πρέπει να γίνει κατανοητό από όλους πριν αρχίσουμε την θεωρητική εισαγωγή αυτής της εργαστηριακής άσκησης είναι ο PC. PC – ProgramCounter O PC ( Απαριθμητής Προγράμματος ελληνιστί ) είναι ένας Register ο οποίος δείχνει κάθε φορά την διεύθυνση μνήμης της επόμενης εντολής. Για να είμαστε πιο συγκεκριμένoi, δείχνει το επόμενο byte προγράμματος που πρόκειται να εκτελεστεί από την ROM. Μετά την εκτέλεση της εντολής (οδηγίας) αυτόματα αυξάνεται κατά 1, έτσι ώστε να δείχνει κάθε φορά το επόμενο byte της επόμενη εντολής προς εκτέλεση (για παράδειγμα η εντολή μπορεί να είναι 2 bytes, έτσι αυτός θα δείξει αρχικά το low byte και στην συνέχεια το high byte). Τα bytes αυτά οδηγούνται στο stack ( στοίβα ελληνιστί ) όπου εκεί έχουμε τον SP ( Stack Pointer ) να δείχνει πάντα την κορυφή (top) της σωρού-stack. Στο συγκεκριμένο παράδειγμα, αν έχουμε 16bit εντολή ( aka 2 bytes) τότε το περιεχόμενο το SP θα αυξηθεί κατά 2. Το περιεχόμενό PC μπορεί να τροποποιηθεί μόνο με τις παρακάτω εντολές: [ATTACH]7081[/ATTACH] Αξίζει να αναφέρουμε ότι είναι 16bit Register, το οποίο είναι κάτι που σημαίνει ότι μπορεί να μεταδώσει 64k πληροφορίας μέσω του 16bit Address Bus του Intel 8051 processor. Go To Παλιότερα στον δομημένο προγραμματισμό ( structured programming ) υπήρχε (και υπάρχει μέχρι και σήμερα για λόγους προς τα πίσω συμβατότητας) η εντολή Go To. Αυτή η εντολή έκανε ένα άλμα από το ένα μέρος στο κώδικα του προγράμματος. Αντίστοιχα το ίδιο μπορούμε να κάνουμε και στην Assembly, μόνο που αντί για Go To, τώρα η εντολή λέγεται JMP ( JUMP – άλμα ). Αυτό μας βολεύει αρκετές φορές να το χρησιμοποιούμε, και στην ουσία είναι μία εντολή που μεταβάλει τον PC . Στην πιο απλή της μορφή, μπορεί να χρησιμοποιηθεί ως : JMP κάπου Και σε πιο σύνθετη περίπτωση να συμπεριλάβει μία συνθήκη ( if conditionals ) . Όπου αν και μόνον αν ισχύει κάτι, τότε κάνε JMP κάπου, αλλιώς μην κάνει τίποτα και συνέχισε το πρόγραμμα κανονικά. Μερικές συνθήκες είναι οι: Z = Zero NZ = Not Zero C = Carry NC = Not Carry B = Bit (1) NB = Not Bit (0) *Προσέξετε επίσης την εντολή: BC=Bit and Clear (αν το bit είναι 1, μηδένισε το ). Οι συνθήκες αυτές έχουν να κάνουν με την Boolean τιμή της συνθήκης. Αν η συνθήκη είναι αληθής τότε έχουμε JMP κάπου ( εννοείται πως έχουμε δηλώσει «πού») αλλιώς αν η συνθήκη είναι ψευδής, τότε έχουμε κανονικά την συνέχιση εκτέλεσης του προγράμματος. Ο έλεγχος αυτός, είναι καθαρά σε πολύ χαμηλό επίπεδο μεταξύ bytes ή bits. Ο έλεγχος ενός bit είναι πολύ απλός και αρκετά σημαντικός. Στην ουσία, αφού το bit έχει δύο καταστάσεις ( λογικό μηδέν, λογικό ένα ) αυτό σημαίνει ότι μπορεί να γίνουν οι παραπάνω έλεγχοι του πίνακα. Η λογική πίσω από τον έλεγχο ενός bit βρίσκεται στην λειτουργία του PSW και των flags αυτού. Για παράδειγμα αν θέλουμε να δούμε αν ένας αριθμός είναι άρτιος ή περιττός και να κάνουμε κάποια ενέργεια για την μία ή την άλλη περίπτωση αρκεί να ελέγξουμε το 1ο bit του PSW, γνωστό ως Parity. Ο έλεγχος bytes έχει να κάνει με την σύγκριση δύο bytes ( μεγαλύτερο, μικρότερο, ίσο, διάφορο). Διακλάδωση Όπως είπαμε πριν, δεν θα είχε νόημα απλά να κάνουμε έναν έλεγχο χωρίς να γίνει κάποια λειτουργία – καθώς θα ήταν άστοχο και άσκοπο από άποψη κατανάλωσης επεξεργαστικών πόρων και clocks. Για αυτό τον λόγο έρχονται τώρα να υλοποιηθούν τα JMP ( Jumps ) που λέγαμε νωρίτερα στην αρχή της θεωρητικής εισαγωγής. Το όλο σχέδιο, είναι να γίνει έλεγχος και κατόπιν του αποτελέσματος που θα προκύψει ( αληθής ή ψευδής) να γίνει ένα JMP σε κάποιο σημείο στο οποίο υπάρχει ο κώδικας με τις λειτουργίες που θέλουμε να εκτελεστούν. Οι εντολές είναι ίδιες με πριν, μόνο που μπαίνει μπροστά ένα J το οποίο υποδηλώνει ότι θα γίνει άλμα ( JMP ) αν η συνθήκη είναι αληθής και το μέρος που θέλουμε να γίνει το jump. Αυτή την διαδικασία την ονομάζουμε διακλάδωση. Για bit JZ κάπου = Jump if Zero JNZ κάπου = Jump if Not Zero JC κάπου = Jump if Carry JNC κάπου = Jump if Not Carry JB κάπου = Jump if Bit (1) JNB κάπου = Jump if Not Bit (0) Η μόνη λειτουργία που μπορούμε να κάνουμε on the fly είναι η εκκαθάριση του bit με την εντολή BC à JBC κάπου ( Jump and Clear if Bit (1) ) [ATTACH]7082[/ATTACH] Οι εντολές αυτές είναι σωστές κατόπιν ελέγχουμε ένα και μόνο ένα bit ή θέση μνήμης που είναι bit addressable. Για byte Αυτό που αλλάζει είναι ότι στην ήδη υπάρχουσα διακλάδωση ενός bit προσθέτουμε το γράμμα C à Compare . Αν θυμάστε είπαμε νωρίτερα ότι ο έλεγχος μεταξύ bytes σχετίζεται με την σύγκριση αυτών. Τα bytes αυτά μπορεί να είναι θέσεις μνήμης ή Registers (πχ Bank Registers ή SFR Registers ). [ATTACH]7083[/ATTACH] Το γράμμα D όπως φαίνεται στο πεδίο Operation (λειτουργία) μειώνει κατά ένα αν και μόνον αν η συνθήκη είναι αληθής. Πολύ σημαντικό σημείο που πρέπει να δώσετε προσοχή είναι η εντολή CJNE( Compare and Jump if Not Equal) . Αυτή η εντολή επηρεάζει το Carry. Αν έχουμε Α >=Β τότε κάνει το Carry μηδενίζεται, αλλιώς γίνεται 1. Αυτό μας επιτρέπει να εισάγουμε με πλάγιο τρόπο την έννοια του else με μετέπειτα έλεγχο στο CY bit του PSW. Κατηγοριοποίηση διακλαδώσεων Αφού αναλύσαμε τις διακλαδώσεις σε bit και byte καθώς και τις λειτουργίες που έχει η κάθε μια ήρθε η στιγμή να οργανώσουμε λίγο τα πράγματα. Αρχικά έχουμε δύο ειδών διακλαδώσεις: 1) Μακρινή ή απόλυτη <χωρίς συνθήκη> a. Άμεση b. Έμμεση 2) Κοντινή ή Σχετική <με συνθήκη> Αυτό που πρέπει να γνωρίζουμε για την Μακρινή Διακλάδωση ( Long JuMP) είναι ότι μπορεί να γίνει σε 64k θέσεις στην μνήμη. Η πιο απλή μορφή (άμεση) είναι 3bytes γιατί η εντολή (που είναι 2byte ) ακολουθείται από κωδικό λειτουργίας της εντολής (που είναι 1byte). H έμμεση διακλάδωση σχηματίζεται με το άθροισμα του DPTR και του ACC. Αυτό που πρέπει να γνωρίζουμε για την Κοντινή Διακλάδωση ( Short JuMP) είναι ότι αποτελείται από 2 bytes. Δεν μπορούμε να κάνουμε διακλαδώσεις πέρα από το όρια [-128, 127]. ΠΕΙΡΑΜΑΤΙΚΗ ΔΙΑΔΙΚΑΣΙΑ ΑΣΚΗΣΗ 5.1 Γράψτε ένα πρόγραμμα που να προσθέτει τα περιεχόμενα των αριθμών των 16bitsπου περιέχονται στη μνήμη, ο μεν πρώτος στις θέσεις κωδ1 (high) και kvd1+1 (low, ο δε δεύτερος στις θέσεις κωδ2 (high) και κωδ2+1 ( lowbyte_. Toαποτέλεσμα να φυλάγεται στις θέσεις μνήμης 20h (high), 21h(medium) και 22h (lowbyte). cseg at 0[/SIZE] [SIZE=2] mov 60h,#1100b ;high byte 1 mov 61h,#1000b ;low byte 1 mov 50h,#0110b ;high byte 2 mov 51h,#0100b ;low byte 2[/SIZE] [SIZE=2] mov A,61h add A,51h mov 22h,A[/SIZE] [SIZE=2] mov A,60h addc A,50h mov 21h, A[/SIZE] [SIZE=2] JC HALT ;if C==1 sunexise | else go to HALT mov 20h,#1 HALT: jmp HALT[/SIZE] [SIZE=2] end ΑΣΚΗΣΗ 5.2 Γράψτε ένα πρόγραμμα που να αντικαθιστά τον προσημασμένο αριθμό των 16bitsπου περιέχεται στη μνήμη στις θέσεις κωδ2h+7 (high) και κωδ2h+8 (lowbyte) με την απόλυτη τιμή του. cseg at 0[/SIZE] [SIZE=2] mov 20h,#11111111b ;high byte 1 mov 21h,#11111110b ;low byte 1[/SIZE] [SIZE=2] jnb 20h.7, HALT ;if bit==0 then go to HALT clr c ; gia tin aferesi mov A,#0h subb A,21h mov 21h,A mov A,0h subb A,20h mov 20h,A HALT: jmp HALT[/SIZE] [SIZE=2] end ΑΣΚΗΣΗ 5.3 Γράψτε πρόγραμμα που να προσθέτει τα περιεχόμενα των θέσεων μνήμης από κωδ1 μέχρι κωδ1+15 στο συσσωρευτή. Αγνοήστε τα κρατούμενα που θα προκύψουν από τις προσθέσεις. cseg at 0 ;Gemizo 40 mexri 4F tis 8eseis me assous mov R0,#40h mov R3,#0Fh gemise:mov A,#1 mov @R0,A inc R0 djnz R3,gemise mov A,#0h ; ka8arise pleon ton A ; teleiose i diadikasia gemismatos mov R1,#40h mov R7,#0Fh[/SIZE] [SIZE=2] loop:add A,@ R1 inc R1 djnz R7,loop HALT:jmp HALT end ΑΣΚΗΣΗ 5.4 Παράδειγμα 1 Να διαβαστεί στο συσσωρευτή ο μεγαλύτερος από τους δύο αριθμούς των θέσεων μνήμης 30hκαι 31h. cseg at 0 ;Gemisma 8eseon mov 30h,#1h mov 31h,#2h[/SIZE] [SIZE=2] MOV A,31h CJNE A,30h,NEXT ; if ( A >= 31h ) then ; C = 0 (isxuei) ; else ; C = 1 (den isxuei) NEXT: JNC HALT ; An einai 0 -- diladi isxuei, termatise MOV A,30h ; Ara einai C==1 HALT: JMP HALT end Παράδειγμα 2 Να αντικατασταθεί το περιεχόμενο της θέσης μνήμης 30hμε τη 15hαν είναι μικρότερο από 16h. cseg at 0 ;Gemisma 8eseon mov 30h,#1h[/SIZE] [SIZE=2] MOV A,30h CJNE A,#16h,NEXT ; if ( A >= 16h ) then ; C = 0 (isxuei) ; else ; C = 1 (den isxuei) NEXT: JNC HALT ; An einai 0 -- diladi isxuei, termatise MOV 30h,#15h ; Ara einai C==1 HALT: JMP HALT end Παράδειγμα 3 Αν ο αριθμός που περιέχεται στη θέση 30hείναι μεγαλύτερος από 7 να αυξηθεί κατά 1 η θέση 31hαλλιώς να μειωθεί κατά 1. cseg at 0 ;Gemisma 8eseon mov 30h,#1h mov 31h,#5h[/SIZE] [SIZE=2] MOV A,30h CJNE A,#07h,NEXT ; if ( A >= 7h ) then ; C = 0 (isxuei) ; else ; C = 1 (den isxuei) NEXT: JNC AFKSISE ; An einai 0 -- diladi isxuei pane sto AFKSISE DEC 31h ; Ara einai C==1 JMP HALT[/SIZE] [SIZE=2] AFKSISE: inc 31h HALT: JMP HALT end ΑΣΚΗΣΗ 5.5 Γράψτε πρόγραμμα που να αυξάνει κατά 1 το περιεχόμενο της θέσης μνήμης κωδ1 αν αυτό είναι περιττός αριθμός και μεγαλύτερος του #κωδ2. cseg at 0[/SIZE] [SIZE=2] ;Gemisma 8eseon mov 30h,#5h ;kod1 mov 31h,#1h ;kod2[/SIZE] [SIZE=2] MOV A,30h CJNE A,31h,NEXT ; if ( A >= 31h ) then ; C = 0 (isxuei) ; else ; C = 1 (den isxuei) NEXT: JNC PERITOS ; An einai 0 -- diladi isxuei pane sto AFKSISE ; Ara einai C==1 JMP HALT[/SIZE] [SIZE=2] PERITOS: JNB P, AFKSISE jmp HALT AFKSISE: INC 30h HALT: JMP HALTend ΣΥΜΠΕΡΑΣΜΑΤΑ Κκαταφέραμε να πραγματοποιήσουμε και να κατανοήσουμε τις διακλαδώσεις ή αλλιώς αυτό που λέμε If-Else στον προγραμματισμό. Αποτελεί ένα πολύ δυνατό εργαλείο για την συνέχεια και σίγουρα θα μας βοηθήσει στις επόμενες ασκήσεις. Χρειάζεται εξοικείωση με τις εντολές ώστε να γνωρίζουμε πότε αυτές τρέχουν και τι τρέχουν. Με αυτό τον τρόπο μπορούμε να επηρεάζουμε τον PC – απαριθμητή προγράμματος και να τον αναγκάζουμε να ανεβοκατεβαίνει στην μνήμη για να βρει εκεί που κάνουμε JMP κάθε φορά. Ο έλεγχος των bits και των bytes παίζει σημαντικό ρόλο ως έλεγχος αλλά και ως built-in λειτουργίες που έχει (όπως πχ να συγκρίνει και δίνει τιμή στο Carry, κάνει Clear ένα bit κλπ κλπ ). Link to comment Share on other sites More sharing options...
Dr.Paneas Ιανουάριος 26, 2010 Author #5 Κοινοποίηση Ιανουάριος 26, 2010 ΣΤΟΙΒΑ ΚΑΙ ΥΠΟΡΟΥΤΙΝΕΣ Σύντομη θεωρητική εισαγωγή Τι είναι στοίβα ( stack) Στοίβα είναι ο χώρος της εσωτερικής έμμεσης μνήμης RAM στον οποίο αποθηκεύονται (φύλαξη) και εξέρχονται (ανάκληση) δεδομένα. Η δομή της στοίβας είναι LIFO – Last In First Out . Συνεπώς κάθε φορά που δίνουμε την εντολή POP (ανάκληση) βγάζουμε από την στοίβα το τελευταίο στοιχείο που υπάρχει στην κορυφή της. Αντίστοιχα κάθε φορά που δίνουμε PUSH ( φύλαξη) στέλνουμε στην δεδομένα στην κορυφή της στοίβας. Για να γνωρίζουμε κάθε φορά την κορυφή της στοίβας, αρκεί να γνωρίζουμε την διεύθυνση αυτής. Την χρήσιμη αυτή πληροφορία μας την δίνει ο Stack Pointer ( Δείκτης Στοίβας) ή αλλιώς SP Register , οποίος είναι SFR στην θέση 81h. Η δουλειά του είναι να δείχνει διαρκώς την κορυφή της στοίβας. Για αυτό λίγο πριν δώσουμε την εντολή PUSH αυτός αυξάνεται κατά ένα, αντίστοιχα λίγο πριν δώσουμε την εντολή POP, μειώνεται κατά ένα. WARNING: Απαγορεύεται να πειράξουμε χειροκίνητα την τιμή του SP γιατί ο CPU θα μπερδευτεί και θα χάσει την κορυφή της στοίβας. Μερικές εντολές που αλλάζουν Μετονομασία Καταχωρητή: MOV A,#12 à MOV ACC,#12 Επίσης για τους Bank Registers είτε θα δώσουμε την διεύθυνση μνήμης τους: εντολή: PUSH 0 Ή θα δηλώσουμε αρχικά στον assembler ότι έχουμε ενεργεί την Bank 1, γράφοντας την εντολή : using 1 Και στην συνέχεια γράφοντας την εντολή έτσι όπως θα την γράφαμε: εντολή : PUSH R4 Τι είναι υπορουτίνες ( Subroutines) Είναι ένα μικρό υποπρόγραμμα ή συνάρτηση ( function ) στον προγραμματισμό, όπου έχει αναλάβει να κάνει μία συγκεκριμένη επεξεργασία στα δεδομένα που δέχεται ως ορίσματα και να τα επιστρέφει με νέες τιμές. Για παράδειγμα αν θέλουμε να ελέγξουμε 50 θέσεις μνήμης ανά ζεύγη, τότε προφανώς θα προγραμματίσουμε μία υπορουτίνα να το κάνει για 2 ζεύγη μέσα σε ένα βρόγχο επανάληψης. Οι συναρτήσεις κάνουν το πρόγραμμα πιο ευανάγνωστο και συντηρήσιμο. ΠΕΙΡΑΜΑΤΙΚΗ ΔΙΑΔΙΚΑΣΙΑ ΑΣΚΗΣΗ 6.1 Σε αυτήν την άσκηση θα δούμε ένα πρόγραμμα το οποίο να ανταλλάσει υα περιεχόμενα 2 θέσεων μνήμης. Στην συγκεκριμένη περίπτωση οι 2 θέσεις θα είναι οι 3hκαι η 35h.Ο κώδικας του προγράμματος είναι: cseg at 0 ;Theseis mnimis[/SIZE][/FONT] [FONT=Tahoma][SIZE=2] KOD1 equ 3h KOD2 equ 5h ;1o Bima[/SIZE][/FONT] [FONT=Tahoma][SIZE=2] mov SP,#7Fh ; Dinoyme timi ston SP mov R0,#KOD1[/SIZE][/FONT] [FONT=Tahoma][SIZE=2] mov A,#KOD2 using 0 ;Dilosi ston assembler oti exoume energi tin Bank0[/SIZE][/FONT] [FONT=Tahoma][SIZE=2] push ar0 ;Fulakse to periexomeno tou R0 push acc pop ar0 pop acc HALT:jmp HALT[/SIZE][/FONT] [FONT=Tahoma][SIZE=2] end ΑΣΚΗΣΗ 6.2 Σε αυτήν την άσκηση πρέπει να γράψουμε ένα πρόγραμμα το οποίο να ανακαλεί στον καταχωρητή Β το περιεχόμενο της κορυφής της στοίβας χωρίς να χαλά αυτή ,ούτε και ο SP.Ο κώδικας του είναι: cseg at 0 ;Theseis mnimis[/SIZE][/FONT] [FONT=Tahoma][SIZE=2] KOD1 equ 3h B_Register equ 0F0h ;1o Bima[/SIZE][/FONT] [FONT=Tahoma][SIZE=2] mov SP,#7Fh ; Dinoyme timi ston SP mov 7Fh,#KOD1 ;Dino mia timi[/SIZE][/FONT] [FONT=Tahoma][SIZE=2] pop B_Register ; decrement SP[/SIZE][/FONT] [FONT=Tahoma][SIZE=2] push B_Register ; increment SP HALT:jmp HALT[/SIZE][/FONT] [FONT=Tahoma][SIZE=2] end ΑΣΚΗΣΗ 6.3 Σε αυτήν την άσκηση πρέπει να φτιάξουμε μία υπορουτίνα που να γράφει το περιεχόμενο του συσσωρευτή Α στον καταχωρητή R5 ,αν το περιεχόμενο του Α είναι μεγαλύτερο του R5.Ο κώδικας προγράμματος γι αυτό το πρόβλημα είναι: cseg at 0 ;Theseis mnimis[/SIZE][/FONT] [FONT=Tahoma][SIZE=2] KOD1 equ 3h KOD2 equ 5h ;1o Bima[/SIZE][/FONT] [FONT=Tahoma][SIZE=2] mov SP,#7Fh ; Dinoyme timi ston SP mov A,#KOD2 ; A=5[/SIZE][/FONT] [FONT=Tahoma][SIZE=2] mov R5,#KOD1 ;R5=3 CJNE A,05h, next[/SIZE][/FONT] [FONT=Tahoma][SIZE=2] next: JC HALT call subr1 ; SP -> apo 7Fh + 2 = 81h HALT:jmp HALT[/SIZE][/FONT] [FONT=Tahoma][SIZE=2] subr1:[/SIZE][/FONT] [FONT=Tahoma][SIZE=2] mov R5,A RET ; SP -> apo 81h - 2 = 7Fh end ΑΣΚΗΣΗ 6.4 Σε αυτήν την άσκηση θέλουμε να γραφτεί στον καταχωρητή R5 o μεγαλύτερος αριθμός από τους αριθμούς που υπάρχουν στις θέσεις 8000h+KOD2 μέχρι 8003h+KOD2,όπου το KOD2=35h. Ο κώδικας προγράμματος γι αυτό το πρόβλημα είναι: cseg at 0 ;Theseis mnimis[/SIZE][/FONT] [FONT=Tahoma][SIZE=2] KOD1 equ 3h KOD2 equ 5h ;1o Bima - Initialize SP[/SIZE][/FONT] [FONT=Tahoma][SIZE=2] mov SP,#7Fh ; Dinoyme timi ston SP ;2 Bima - Gemizo 8000h+KOD2 mexri 8003h+KOD2 tis 8eseis me times 1++[/SIZE][/FONT] [FONT=Tahoma][SIZE=2] MOV DPTR,#8000h+KOD2 ;Arxikopoio ton DPTR MOV A,#1h ; Arxikopoio ton A MOV R5,A ; Proti mnimi ston R5[/SIZE][/FONT] [FONT=Tahoma][SIZE=2] call rFILL call rFILL call rFILL jmp HALT[/SIZE][/FONT] [FONT=Tahoma][SIZE=2] HALT:jmp HALT rFILL:[/SIZE][/FONT] [FONT=Tahoma][SIZE=2] MOVX @DPTR,A CJNE A,05h, COMPARE ; if epomeni mnimi >= proigoumenis mnimis SYNEXISE: INC A INC DPTR RET COMPARE:[/SIZE][/FONT] [FONT=Tahoma][SIZE=2] JC SYNEXISE mov R5,A JMP SYNEXISE RET end ΑΣΚΗΣΗ 6.5 Σε αυτήν την άσκηση μας ζθτείται ένα πρόγραμμα το οποίο να κάνει χρονική καθυστέρηση της τάξεως των 0,2s χρησιμοποιώντας την παρακάτω υπορουτίνα : cseg at 0 mov SP,#7Fh[/SIZE][/FONT] [FONT=Tahoma][SIZE=2] mov A,#10h call subr1[/SIZE][/FONT] [FONT=Tahoma][SIZE=2] inc A[/SIZE][/FONT] [FONT=Tahoma][SIZE=2] mov DPTR,#0CC00h movx @DPTR,A HALT:jmp HALT subr1:[/SIZE][/FONT] [FONT=Tahoma][SIZE=2] DELAY: MOV R6, #0C3h DELAY1: MOV R7, #0FFh DELAY2: NOP NOP DJNZ R7, DELAY2 DJNZ R6, DELAY1 RET END Το πρόγραμμα καθώς και η χρονική καθυστέρηση που προκαλεί φαίνεται στην παρακάτω εικόνα : [ATTACH]7084[/ATTACH] Όπως βλέπουμε ο χρόνος που κάνει να εκτελεστεί ατό το πρόγραμμα είναι 0,19946s που είναι πάρα πολύ κοντά στα 0,2s. ΑΣΚΗΣΗ 6.6 Σε αυτήν την άσκηση πρέπει να γράψουμε τις παρακάτω εντολές DEDOMENA segment idatarseg DEDOMENAds 64cseg at 0movSP,#STOIBA-1 . . . . . . Και να τις ενσωματώσουμε σε ένα πρόγραμμα. Στην συνέχεια θα δούμε τον χώρο τον οποίο δεσμεύσαμε για την στοίβα ανοίγοντας τον φάκελο .m51 Ο κώδικας του προγράμματος είναι: [ATTACH]7085[/ATTACH] και ανοίγοντας το αρχείο .M51 παρατηρούμε ότι η θέση που δεσμεύει για την στοίβα είναι είναι από τις θέσεις μνήμης 0008h(που είναι η defaultαπό το πρόγραμμα αρχή της στοίβας ) μέχρι την θέση μνήμης 0040h,δηλαδή 64 θέσεις μετά ,όσο δηλώσαμε εμείς δηλαδή με την εντολή : ds 64 [ATTACH]7086[/ATTACH] Αλλάζοντας το ds σε 32 όπως μα ζητείται από τις σημειώσεις τότε παρατηρούμε ότι και οι θέσεις μνήμης που δεσμεύονται από τη στοίβα μειώνονται στο μισό. Παρακάτω παρατίθεται ο κώδικας προγράμματος γι αυτό καθώς και το αρχείο .m51 : [ATTACH]7087[/ATTACH] Παρατηρούμε ότι αντί για 0040h που ήταν πριν έχει πάει στο 0020h δηλαδή 32 θέσεις. Link to comment Share on other sites More sharing options...
Dr.Paneas Ιανουάριος 26, 2010 Author #6 Κοινοποίηση Ιανουάριος 26, 2010 Μερικές ασκήσεις χωρίς εκφώνηση, για να βρείτε μόνοι σας τι κάνουν // 7.1 cseg at 0 MOV A,#00100101b HALT: //A MOV C,ACC.0 ANL C,ACC.1 // 1 && 1 MOV ACC.0,C //B MOV C,ACC.2 ORL C,ACC.3 // 1 || 1 MOV ACC.2,C //C MOV C,ACC.4 CPL C // NOT C MOV ACC.4,C //d MOV C,ACC.5 CPL C ANL C,ACC.6 // !x*y MOV F0,C // result is saved to F0 MOV C,ACC.5 ANL C,/ACC.6 // x*!y ORL C,F0 // 0 || 1 MOV ACC.5,C //E MOV C, ACC.7 MOV ACC.7, Cjmp HALTend // 7.2 cseg at 0 //Esto KOD1 = 20h //ESTO KOD1+1 = 21h //ESTO KOD1+2 = 22h MOV 20h,#0h MOV 21h,#11111111b MOV 22h,21h //A MOV ACC,#00001111b MOV C,ACC.0 // Vazo C=1 MOV 20h.2,C //B CPL C // NOT C ==> C=0 MOV 21h.4,C MOV 21h.5,C MOV 21h.6,C MOV 21h.7,C //C CPL 22h.0 CPL 22h.1 CPL 22h.2 CPL 22h.3HALT:jmp HALTend // 7.3 cseg at 0 MOV A,#1h HALT: MOV 0A0h,A RL Ajmp HALTend // 7.4 cseg at 0 //Esto KOD2=40h //Esto KOD2+15 = 4F ;Gemizo 40 mexri 4F tis 8eseis me assous mov R0,#40h mov R3,#0Fh mov A,#0h gemise: inc A mov @R0,A inc R0 djnz R3,gemise mov A,#0h ; ka8arise pleon ton A ; teleiose i diadikasia gemismatos // Pollplasiase oles tis times epi 2 mov R0,#40h mov R3,#0Fh MOV A,@R0 pollaplasiase: MOV A,@R0 RL A ; shift aristera mov @R0,A inc R0 djnz R3,pollaplasiaseHALT:jmp HALT // 7.5 cseg at 0 clr C mov r5,#10001110b //artios mov 20h,r5 jb 20h.0,next //an perittos pane sto next jnb 20h.0,carr //an artios pane sto carr next: setb acc.0 carr: setb CHALT:jmp HALTend Link to comment Share on other sites More sharing options...
Dr.Paneas Ιανουάριος 26, 2010 Author #7 Κοινοποίηση Ιανουάριος 26, 2010 TEXNIKEΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ Σύντομη θεωρητική εισαγωγή ΒΡΟΧΟΣ (LOOP) Ο βρόχος είναι μία πολύ συνηθισμένη τεχνική στον προγραμματισμό (βλέπε for, do_while, while ) . Στην Assembly έχουμε μία standard τυποποίηση αυτής της επανάληψης έτσι ώστε να είναι πιο εύκολο το πρόγραμμα κατά τη συγγραφή σου. Ο βρόχος μπορεί είτε να αρχίζει από τον μετρητή μηδενισμένο και να αυξάνεται ως ότου φτάσει τον αριθμό των επιθυμητών επαναλήψεων ή να αρχίζει από τον αριθμό των επαναλήψεων και να μειώνεται μέχρι το μηδέν. Όταν έχουμε 2 byte, συνιστάται η χρήση εμφωλευμένης loop. Σύγκριση προσιμασμένων αριθμών Το αν ο αριθμός είναι προσιμασμένος ή όχι, φαίνεται από το 7ο bit. Το πρόσημα του αποτελέσματος της αφαίρεσης ελέγχεται από το bit ACC.7 ενώ η ορθότητα του αποτελέσματος από το bit Overflow. Αφαιρώντας από τον αριθμό τη σταθερά ΔΕ θα πρέπει να προκύψει αρνητικό αποτέλεσμα. ΠΕΙΡΑΜΑΤΙΚΗ ΔΙΑΔΙΚΑΣΙΑ ΑΣΚΗΣΗ 10.1 Επαληθεύστε ότι η εντολή MUL για τον πολλαπλασιασμό δύο προσημασμένων αριθμών δίνει λάθος αποτέλεσμα: ΑΣΚΗΣΗ 10.2 ΔΙΝΕΤΑΙ ΕΝΑΣ ΠΙΝΑΚΑΣ ΣΤΗΝ ΜΝΗΜΗ ΠΡΟΓΡΑΜΜΑΤΟΣ ΣΤΙΣ ΔΙΕΥΘΥΝΣΕΙΣ ΑΠΟ 8000h ΜΕΧΡΙ 803Fh ΠΟΥ ΠΕΡΙΕΧΕΙ ΠΡΟΣΗΜΑΣΜΕΝΟΥΣ ΑΡΙΘΜΟΥΣ ΤΩΝ 2 BYTES. ΝΑ ΓΡΑΦΕΙ ΠΡΟΓΡΑΜΜΑ ΠΟΥ ΝΑ ΔΗΜΙΟΥΡΓΕΙ ΕΝΑΝ ΔΕΥΤΕΡΟ ΠΙΝΑΚΑ ΣΤΗΝ ΕΣΩΤΕΡΙΚΗ ΜΝΗΜΗ RAM ΣΤΙΣ ΔΙΕΥΘΥΝΣΕΙΣ ΑΠΟ 0C0h ΜΕΧΡΙ 0FFh ΠΟΥ ΝΑ ΠΕΡΙΕΧΕΙ ΤΙΣ ΑΠΟΛΥΤΕΣ ΤΙΜΕΣ ΤΩΝ ΑΡΙΘΜΩΝ ΤΟΥ ΠΡΩΤΟΥ ΠΙΝΑΚΑ. ΑΣΚΗΣΗ 10.3 NA ΓΡΑΦΕΙ ΠΡΟΓΡΑΜΜΑ ΠΟΥ ΝΑ ΒΡΙΣΚΕΙ ΤΟ ΜΕΓΑΛΥΤΕΡΟ ΚΑΙ ΤΟ ΜΙΚΡΟΤΕΡΟ ΑΠΟ ΤΟΥΣ ΑΡΙΘΜΟΥΣ ΠΟΥ ΠΕΡΙΕΧΟΝΤΑΙ ΣΤΗΝ ΕΞΩΤΕΡΙΚΗ ΜΝΗΜΗ RAM ΣΤΙΣ ΔΙΕΥΘΥΝΣΕΙΣ ΑΠΟ 8000h ΜΕΧΡΙ 80FFh. O ΜΕΓΑΛΥΤΕΡΟΣ ΑΡΙΘΜΟΣ ΝΑ ΓΡΑΦΕΙ ΣΤΗ ΘΕΣΗ ΜΝΗΜΗΣ 20h ΚΑΙ Ο ΜΙΚΡΟΤΕΡΟΣ ΣΤΗΝ ΑΜΕΣΩΣ ΕΠΟΜΕΝΗ. ΟΙ ΘΕΣΕΙΣ ΤΩΝ ΑΡΙΘΜΩΝ ΝΑ ΦΥΛΑΓΟΝΤΑΙ ΣΤΙΣ ΔΙΕΥΘΥΝΣΕΙΣ 22h – 23h ΓΙΑ ΤΟΝ ΜΕΓΑΛΥΤΕΡΟ 24h – 25h ΓΙΑ ΤΟΝ ΜΙΚΡΟΤΕΡΟ. ΑΣΚΗΣΗ 10.4 Η ΠΕΡΙΟΧΗ ΕΞΩΤΕΡΙΚΗΣ ΜΝΗΜΗΣ RAM ΜΕ ΔΙΕΥΘΥΝΣΕΙΣ ΑΠΟ 8000Η ΜΕΧΡΙ 8FFFh ΠΕΡΙΕΧΕΙ ΠΡΟΣΗΜΑΣΜΕΝΟΥΣ ΑΡΙΘΜΟΥΣ ΤΩΝ 16 bits. ΓΡΑΨΤΕ ΕΝΑ ΠΡΟΓΡΑΜΜΑ ΝΑ ΕΛΕΓΧΕΙ ΑΥΤΗΝ ΤΗΝ ΠΕΡΙΟΧΗ ΚΑΙ ΝΑ ΜΕΤΡΑ ΤΟΥΣ ΑΡΙΘΜΟΥΣ ΠΟΥ ΕΙΝΑΙ ΜΕΓΑΛΥΤΕΡΟΙ ΑΠΟ -10 ΚΑΙ ΜΙΚΡΟΤΕΡΟΙ Η ΙΣΟΙ ΑΠΟ +10. ΥΠΟΛΟΓΙΣΤΕ ΤΟ ΧΡΟΝΟ ΕΚΤΕΛΕΣΗΣ ΤΟΥ ΠΡΟΓΡΑΜΜΑΤΟΣ, ΑΦΟΥ ΤΟ ΤΡΕΞΕΤΕ. ΑΣΚΗΣΗ 10.5 ΝΑ ΓΡΑΦΕΙ ΠΡΟΓΡΑΜΜΑ ΠΟΥ ΝΑ ΠΟΛΛΑΠΛΑΣΙΑΖΕΙ ΤΟΥΣ ΔΥΟ ΠΡΟΣΗΜΑΣΜΕΝΟΥΣ ΑΡΙΘΜΟΥΣ ΤΩΝ ΘΕΣΕΩΝ ΤΗΣ ΕΞΩΤΕΡΙΚΗΣ ΜΝΗΜΗΣ 1030Η ΚΑΙ 1031Η . ΤΟ ΑΠΟΤΕΛΕΣΜΑ ΝΑ ΚΑΤΑΧΩΡΕΙΤΑΙ ΣΤΙΣ ΘΕΣΕΙΣ ΜΝΗΜΗΣ 1032Η ΚΑΙ 1033Η . ΑΣΚΗΣΗ 10.6 ΠΙΝΑΚΑΣ 500 ΘΕΣΕΩΝ ΠΟΥ ΑΡΧΙΖΕΙ ΑΠΟ ΤΗ ΔΙΕΥΘΥΝΣΗ ΜΝΗΜΗΣ 8000Η ΣΤΗΝ ΕΞΩΤΕΡΙΚΗ RAM . ΚΑΘΕ ΘΕΣΗ ΜΝΗΜΗΣ ΠΕΡΙΕΧΕΙ ΕΝΑΝ ΠΡΟΣΗΜΑΣΜΕΝΟ ΑΡΙΘΜΟ. ΝΑ ΓΡΑΦΕΙ ΠΡΟΓΡΑΜΜΑ ΠΟΥ ΝΑ ΑΠΑΡΙΘΜΕΙ ΣΤΟΝ R7 ΤΟΥΣ ΠΕΡΙΤΤΟΥΣ ΑΡΝΗΤΙΚΟΥΣ ΑΡΙΘΜΟΥΣ. ΑΣΚΗΣΗ 10.7 NA ΓΡΑΦΕΙ ΠΡΟΓΡΑΜΜΑ ΠΟΥ ΝΑ ΑΥΞΑΝΕΙ ΚΑΤΑ 1 ΤΟ ΠΕΡΙΕΧΟΜΕΝΟ ΤΟΥ R7 ΑΝ Ο ΠΡΟΣΗΜΑΣΜΕΝΟΣ ΑΡΙΘΜΟΣ ΤΩΝ 3BYTES ΠΟΥ ΒΡΙΣΚΕΤΑΙ ΣΤΙΣ ΔΙΕΥΘΥΝΣΕΙΣ ΕΞΩΤΕΡΙΚΗΣ ΜΝΗΜΗΣ 1030Η , 1031Η , 1032Η ΕΙΝΑΙ ΜΕΓΑΛΥΤΕΡΟΣ ΑΠΟ ΤΟΝ ΠΡΟΣΗΜΑΣΜΕΝΟ ΑΡΙΘΜΟΣ ΤΩΝ 3 bytes ΤΩΝ ΘΕΣΕΩΝ 1033Η , 1034Η , ΚΑΙ 1035Η Οι κώδικες: //Askisi 10.1 ΕΠΑΛΗΘΕΥΣΤΕ ΟΤΙ Η ΕΝΤΟΛΗ MUL ΓΙΑ ΤΟΝ ΠΟΛΛΑΠΛΑΣΙΑΣΜΟ ΔΥΟ ΠΡΟΣΗΜΑΣΜΕΝΩΝ ΑΡΙΘΜΩΝ ΔΙΝΕΙ ΛΑΘΟΣ ΑΠΟΤΕΛΕΣΜΑ. cseg at 0 MOV A,#0AH ;A=10 MOV B,#0F6H ;B=-10 MOV 20H,A ;TA METAFEROUME SE THESEIS 20H KAI 21H MOV 21H,B ;OPOU MPOREI NA GINEI PROSPELASI KATA BIT MOV R0,AJNB 20H.7, CHECK2 ;AN O PRWTOS DEN EINAI ARNITIKOS PAME NA ELEGKSOUME TO DEFTEROXRL 20H,#0FFH ;AN EINAI ARNITIKOS VRISKOUME TO SIMPLIRWMA TOU WS PROS 2 MOV A,20H ADD A,#1 MOV R0,A ;TWRA O R0 PERIEXEI TO SIMPLIRWMACHECK2: JNB 21H.7,POL1 ;AN O DEFTEROS EINAI THETIKOS, AFOU O PRWTOS EINAI ÔHETIKOS,POLLAPLASIAZOUMEXRL 21H,#0FFH ;AN O DEFTEROS EINAI ARNITIKOS VRISKOUME TO SIMPLIRWMA GIA NA POLLAPLASIASOUME MOV A,21H ADD A,#1 MOV B,APOL1: MOV A,R0 MUL AB MOV R0,A MOV R1,BLOOP: JMP LOOPEND //Askisi 10.2 ΔΙΝΕΤΑΙ ΕΝΑΣ ΠΙΝΑΚΑΣ ΣΤΗΝ ΕΞΩΤΕΡΙΚΗ ΜΝΗΜΗ ΠΡΟΓΡΑΜΜΑΤΟΣ ΣΤΙΣ ΔΙΕΥΘΥΝΣΕΙΣ ΑΠΟ 8000h ΜΕΧΡΙ 803Fh ΠΟΥ ΠΕΡΙΕΧΕΙ ΠΡΟΣΗΜΑΣΜΕΝΟΥΣ ΑΡΙΘΜΟΥΣ ΤΩΝ 2 BYTES. ΝΑ ΓΡΑΦΕΙ ΠΡΟΓΡΑΜΜΑ ΠΟΥ ΝΑ ΔΗΜΙΟΥΡΓΕΙ ΕΝΑΝ ΔΕΥΤΕΡΟ ΠΙΝΑΚΑ ΣΤΗΝ ΕΣΩΤΕΡΙΚΗ ΜΝΗΜΗ RAM ΣΤΙΣ ΔΙΕΥΘΥΝΣΕΙΣ ΑΠΟ 0C0h ΜΕΧΡΙ 0FFh ΠΟΥ ΝΑ ΠΕΡΙΕΧΕΙ ΤΙΣ ΑΠΟΛΥΤΕΣ ΤΙΜΕΣ ΤΩΝ ΑΡΙΘΜΩΝ ΤΟΥ ΠΡΩΤΟΥ ΠΙΝΑΚΑ. cseg at 0 mov DPTR, #8000h mov R0, #0C0h mov R1, #0h goto: movx A, @DPTR mov 20h, A inc DPTR movx A, @DPTR mov 21h, A inc DPTR jnb 20h.7, com1 mov A, 20h cpl A mov 20h, A mov A, 21h cpl A clr C add A, #1h mov 21h, A jnc com1 inc 20h com1: mov @R0, 20h inc R0 mov @R0, 21h inc R0 inc R1 CJNE R1,#20h,goto HALT: jmp HALTend //Askisi 10.3 org 0mov DPTR, #8000hmov 20h, Amov 21h, Alogo:movx A, @DPTRinc DPTRmov R0,DPLcjne R0, #00h, beginloop: jmp loopbegin: cjne A, 20h, com1com1: jc minimmov 20h, Amov 22h, DPHmov 23h, DPLjmp logominim:cjne A, 21h,com2com2: jnc logomov 21h, Amov 24h,DPHmov 25h, DPLjmp logoend κώδικας2 org 0 mov SP, #7Fh mov R0, #00h mov 21h, #0ffh mov 20h, #00h mov DPTR, #7fffhklop: inc DPTR movx A,@DPTR call subr1 djnz R0,kloploop: jmp loopsubr1: cjne A,20h,nextnext : jc opo mov 20h, a mov 22h, 83h mov 23h, 82hopo : cjne a,31h, gotogoto : jnc son mov 31h,a mov 34h,83h mov 35h,82hson : ret end //Askisi 10.4 org 0 mov SP, #7Fh mov R0, #00h mov DPTR, #7fffh mov r7, #00h mov r1, #8h mov r2,#00hklop: inc DPTR movx A,@DPTR mov 20h, a τοποθετούμε κάθε φορά στις διευθύνσεις 20h και 21h inc dptr της εσωτ. μνήμης RAM τους προσημασμένους movx a, @dptr αριθμούς των 2 bytes της εξ. μνήμης RAM mov 21h, acall subr1djnz R0,klopdjnz r1, kloploop: jmp loopsubr1:jb 20h.7, pal mov a, #0ah clr c subb a, 21h mov a,#00h για αρνητικό προσημασμένο αριθμό κάνουμε τη subb a, 20h σύγκριση : -10 < αριθμός jb acc.7, telos jb OV, telos inc r7 jmp telospal : mov a, #0f6h clr c subb a, 21h mov a,#0ffh για θετικό προσημασμένο αριθμό κάνουμε τη subb a, 20h σύγκριση : αριθμός +10 jb acc.7, r7inc jnb OV, telosr7inc:inc r7telos:retend //Askisi 10.5 cseg at 0 mov DPTR,#1030h movx A, @DPTR mov 20h, A mov DPTR,#1031h movx A, @DPTR mov 21h, A mov A, 20h mov B, 21hclr F0jnb 20h.7, com1cpl F0CPL Aadd A, #1hmov 34h, Acom1: jnb 21h.7, com2mov A, 31hcpl F0CPL Aadd A, #1hmov 33h, Amov B, 33hcom2: mul ABmov 33h, Amov 32h, Bmov C, F0jnc loopcpl A mov 44h, Amov A, 32hcpl Amov 43h, Aclr Cmov A, 44hadd A, #01hmov 33h, Ajnc loop inc 32hloop: jmp loopend //Askisi 10.6 ΔΙΝΕΤΑΙ ΠΙΝΑΚΑΣ 500 ΘΕΣΕΩΝ ΠΟΥ ΑΡΧΙΖΕΙ ΑΠΟ ΤΗ ΔΙΕΥΘΥΝΣΗ ΜΝΗΜΗΣ 8000Η ΣΤΗΝ ΕΞΩΤΕΡΙΚΗ RAM. ΚΑΘΕ ΘΕΣΗ ΜΝΗΜΗΣ ΠΕΡΙΕΧΕΙ ΕΝΑΝ ΠΡΟΣΗΜΑΣΜΕΝΟ ΑΡΙΘΜΟ. ΝΑ ΓΡΑΦΕΙ ΠΡΟΓΡΑΜΜΑ ΠΟΥ ΝΑ ΑΠΑΡΙΘΜΕΙ ΣΤΟΝ R7 ΤΟΥΣ ΠΕΡΙΤΤΟΥΣ ΑΡΝΗΤΙΚΟΥΣ ΑΡΙΘΜΟΥΣ.[code]ORG 0 MOV DPTR,#8000H MOV R7,#0H MOV LOOPCNTR, #500LOOP1: MOVX A,@DPTR JNB ACC.7,NEXT JNB ACC.0,NEXT INC R7NEXT: INC DPTR DJNE LOOPCNTR, LOOP1LOOP: JMP LOOPEND //Askisi 10.7 org 0mov SP, #7Fhmov R7, #00hklop: call com1loop: jmp loopcom1: mov A, 35hclr Csubb A, 32hmov A, 34hsubb A, 31hmov A, 33hsubb A, 30hjb ACC.7, R7incjnb OV, stopR7inc: inc R7stop: retend ΣΥΜΠΕΡΑΣΜΑΤΑ Οι ασκήσεις μας βοήθησαν στην ταχύτερη συγγραφή κώδικα συγκεκριμένων code blocks που είναι στάνταρ στον προγραμματισμό. Αξίζει να κρατήσουμε την υλοποίηση της λούπας καθώς και τον έλεγχο προσημασμένων αριθμών. Καθώς επίσης και μία κρυφή διαδικασία που ήταν να βρούμε τον μέγιστο, και να τον αποθηκεύσουμε στις κατάλληλες θέσεις μνήμης. Επίσης, μην ξεχνάτε ότι οι πολλαπλασιασμός πρέπει να γίνεται από θετικούς αριθμούς, μη προσημασμένους. ----- Τα παραπάνω κείμενα ΔΕΝ αποτελούν αντιγραφή. ΔΕΝ αποτελούν μεταφραση. Είναι οι εργασίες μου για την σχολή αυτό το εξάμηνο. Ελπίζω να βοηθήσουν όσους θέλουν να μάθουν Assembly. Πληροφορίες πάρθηκαν από τις σημειώσεις καθηγητών του τμήματος Αυτοματισμού ΑΤΕΙ Σίνδου και Πειραία. Προγράμματα: uVision3 Για να συνδέσετε τον μικροεπεξργαστή στο PC και τον προγραμματίσετε θέλετε το Flip. Καλό coding Link to comment Share on other sites More sharing options...
afro_king Ιανουάριος 27, 2010 #8 Κοινοποίηση Ιανουάριος 27, 2010 να σαι καλα Dr.Panea εκανες πολυ καλη δουλεια. καλη μας επιτυχεια και καλη συνεχεια να εχουμε. Link to comment Share on other sites More sharing options...
oxide Μάϊος 21, 2010 #9 Κοινοποίηση Μάϊος 21, 2010 πολυ ενδιαφερον...εχω ασχοληθει με pic programming αλλα αυτο που θα ηθελα ειναι καποιος προσωμοιοτης (οχι απαραιτητα για pic) για να μπορεσω να παιξω λιγο χωρις breadboard..εχετε κατι να προτεινετε? Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.