Η CPU ενός μικροελεγκτή χρησιμοποιεί μερικούς καταχωρητές για την προσωρινή αποθήκευση δεδομένων τα οποία χρησιμοποιούνται για αριθμητικές καθώς και για λογικές πράξεις. Σε αυτή την ενότητα θα εξετάσουμε μεταξύ άλλων τους καταχωρητές γενικού σκοπού GPRs του μικροελεγκτή AVR και θα επιδείξουμε τη χρήση των GPRs με τις απλές εντολές LDI και ADD.
Ένας τυπικός μικροελεγκτής AVR έχει 32 καταχωρητές γενικού σκοπού GPRs που ονομάζονται R0 έως R31. Οι καταχωρητές GPRs ενός μικροελεγκτή AVR έχουν πλάτος 8-bit. Τα 8-bits ενός καταχωρητή γενικού σκοπού δείχνονται στο ακόλουθο διάγραμμα:
Εδώ φαίνεται η περιοχή από το MSB(most – significant – bit) από την ποιο αριστερή θέση στην οποία βρίσκεται το bit D7 έως στο LSB(least – significant – bit) στην ποιο δεξιά θέση στην οποία βρίσκεται το bit D0.
Οι 32 καταχωρητές γενικού σκοπού ενός μικροελεγκτή AVR βρίσκονται στη χαμηλότερη θέση της μνήμης δεδομένων και μπορούν να χρησιμοποιηθούν από όλες τις αριθμητικές και λογικές εντολές.
Η εντολή LDI
Η εντολή LDI αντιγράφει 8-bit κυριολεκτικές τιμές σε ένα καταχωρητή γενικού σκοπού (GPR):
LDI Rd, K ; φορτώνει στον καταχωρητή Rd την κυριολεκτική αριθμητική τιμή Κ
; d πρέπει να είναι μεταξύ 16 και 31
Σημείωση: Κ είναι μια 8-bit σταθερή τιμή που μπορεί να είναι δεκαδικός 0 – 255 ή δεκαεξαδικός 0x00 – 0xFF ενώ ο Rd είναι ένας καταχωρητής GPR από R16 έως R31 (ένας από την μεγαλύτερη ομάδα καταχωρητών)
Παραδείγματα:
LDI R21, 0x30 ; load R21 with 0x30 (R21 = 0x30)
LDI R28, 0x85 ; load 0x85 into R28 (R28 = 0x85)
Σημείωση: Δεν μπορούμε να φορτώσουμε τιμές σε καταχωρητές από R0 έως R15 χρησιμοποιώντας την εντολή LDI. Για παράδειγμα η ακόλουθη εντολή δεν είναι έγκυρη:
LDI R5, 0x68 ; invalid instruction
Παρατηρήστε στην εντολή LDI τη θέση του καταχωρητή αναχώρησης και εκείνου της άφιξης. Όπως μπορείτε να δείτε η εντολή LDI φορτώνει τον δεξιό τελεστή στον αριστερό τελεστή.
Σημείωση: Για να γράψουμε σχόλια στη γλώσσα Assembly χρησιμοποιούμε τον χαρακτήρα του ελληνικού ερωτηματικού «;». Συγκεκριμένα το υπόλοιπο της γραμμής μετά τον χαρακτήρα του ερωτηματικού αγνοείται. Χρησιμοποιείται για να περιγράψουμε την λειτουργία του κώδικα έτσι ώστε αργότερα ο κώδικας να μπορεί να γίνει κατανοητός.
Σημείωση: Όταν θέλουμε να εισάγουμε ένα δεκαεξαδικό αριθμό τοποθετούμε το σύμβολο του δολαρίου $ ή το 0x μπροστά στην τιμή. Εάν δεν τοποθετήσουμε τίποτα σημαίνει ότι έχουμε δεκαδική τιμή. Για το σύμβολο 0b μπροστά από μια τιμή που είναι σύνολο από 0 και 1 δείχνει δυαδικό αριθμό.
Η εντολή ADD
Η εντολή ADD έχει την ακόλουθη μορφή:
ADD Rd, Rr; πρόσθεσε τα περιεχόμενα του Rr σε εκείνα του Rd και φόρτωσε το αποτέλεσμα πίσω στον Rd
Παράδειγμα:
LDI R19, 0x65 ; load 0x65 into R19
LDI R20, 0x44 ; load 0x44 into R20
ADD R19, R20 ; add value R20 to R19 (R19 = R19 + R20)
Η εντολή MOV
Η εντολή MOV χρησιμοποιείται για να αντιγράψει δεδομένα μεταξύ καταχωρητών γενικού σκοπού GPR από R0 έως R31
MOV Rd, Rr ; Rd = Rr (αντέγραψε τον Rr στον Rd)
; Rd και Rr μπορεί να είναι οποιοδήποτε από τους GPRs
Παράδειγμα:
Η επόμενη εντολή αντιγράφει τα περιεχόμενα του R22 στον R12:
MOV R12, R22 ; R12 = R22
Αν ο R22 περιέχει την τιμή 70 μετά την εκτέλεση της παραπάνω εντολής και οι δυο R22 και R12 θα περιέχουν την ίδια τιμή 70.
Παράδειγμα
Το επόμενο κομμάτι κώδικα προσθέτει την τιμή 0x25 στα περιεχόμενα της θέσης 0x230 της μνήμης δεδομένων και αποθηκεύει το αποτέλεσμα στη θέση 0x235:
LDI R21, 0x25 ; load R21 with 0x25
LDS R22, 0x230 ; load R21 with the contents of location on 0x230
ADD R22, R21 ; R22=R22+R21
STS 0x235, R22 ; store R22 to location 0x235
Η εντολή SUB
Η εντολή SUB έχει την ακόλουθη σύνταξη:
SUB Rd, Rr ; Rd = Rd – Rr
Η εντολή SUB προκαλεί τη CPU να αφαιρέσει την τιμή του καταχωρητή Rr από τον Rd και να βάλει το αποτέλεσμα πίσω στον καταχωρητή Rd.
Παράδειγμα
Στο ακόλουθο κομμάτι κώδικα αφαιρούμε την τιμή 0x30 από την τιμή 0x45:
LDI R18, 0x30 ; R18 = 0x30
LDI R19, 0x45 ; R19 = 0x45
SUB R19, R18 ; R19 = R19 – R18
Παράδειγμα
Το επόμενο κομμάτι κώδικα, αφαιρεί την τιμή 0x08 από τα περιεχόμενα της θέσης 0x350 και αποθηκεύει το αποτέλεσμα στη θέση 0x380:
LDS R10, 0x350 ; R10 = contents of location 0x350
LDI R20, 0x08 ; R20 = 0x08
SUB R10, R20 ; R10 = R10 – R16
STS 0x380, R10 ; store the contents of R10 to location 0x380
Παράδειγμα
Το επόμενο κομμάτι κώδικα μειώνει τα περιεχόμενα του R12 κατά 1:
LDI R18, 0x01
SUB R12, R18
Η εντολή INC
Η εντολή INC έχει την ακόλουθη σύνταξη:
INC Rd ; αύξησε τα περιεχόμενα του Rd κατά 1
Παράδειγμα
Η ακόλουθη εντολή προσθέτει 1 στα περιεχόμενα του R5:
INC R5 ; R5 = R5+1
Παράδειγμα
Το ακόλουθο κομμάτι κώδικα αυξάνει τα περιεχόμενα της θέσης 0x450 της μνήμης δεδομένων κατά 1:
LDS R18, 0x450 ; R18 = contents of location 0x450
INC R18 ; R18 = R18 + 1
STS 0x450, R18 ; store R18 to location 0x450
Η εντολή DEC
Η εντολή DEC έχει την ακόλουθη σύνταξη:
DEC Rd ; Rd = Rd – 1
Η εντολή DEC μειώνει (αφαιρεί 1 από) τα περιεχόμενα του καταχωρητή Rd και βάζει το αποτέλεσμα πίσω στον καταχωρητή Rd.
Παράδειγμα
Η επόμενη εντολή αφαιρεί 1 από τα περιεχόμενα του R14:
DEC R14 ; R10 = R10 – 1
Η εντολή COM
Η εντολή COM Rd παρέχει το συμπλήρωμα ως προς ένα του καταχωρητή Rd και μετά βάζει το αποτέλεσμα πίσω στον Rd. Το συμπλήρωμα ως προς ένα μιας δυαδικής τιμής 8-bit δίνεται αντικαθιστώντας τα 0 με 1 και τα 1 με 0.
Παράδειγμα
Στο επόμενο κομμάτι κώδικα βάζουμε την τιμή 0x55 στον R20 και την στέλνουμε στη θύρα PORTD. Μετά παίρνουμε το συμπλήρωμα ως προς 1 του καταχωρητή R20 που γίνεται 0xAA στο δεκαεξαδικό. Δηλαδή παίρνουμε το συμπλήρωμα της τιμής 01010101 (0x55) που γίνεται 10101010 (0xAA), και το στέλνουμε στη θύρα D:
LDI R20, 0x55 ; R20 = 0x55
OUT PORTD, R20 ; copy R20 to port D (PORTD = 0x55)
COM R20 ; complement R20
OUT PORTD, R20 ; copy R20 to port D (PORTD = 0xAA)