13. Εντολές περιστροφής και μετατόπισης byte

Οι μικροελεγκτές AVR με τις εντολές ROL και ROR εκτελούν περιστροφή ή μετατόπιση κατά ένα bit διαμέσου της σημαίας κρατουμένου. Παρακάτω θα εξετάσουμε αυτές τις εντολές διότι χρησιμοποιούνται ευρέως στον προγραμματισμό.

Περιστροφή διαμέσου του κρατουμένου:

Υπάρχουν δυο εντολές περιστροφής στους AVR που εμπλέκουν τη σημαία κρατουμένου, αυτές είναι οι ROR και ROL.

Η εντολή περιστροφής ROR

ROR  Rd    ;   rotate Rd right through carry

Με την εντολή ROR τα bits ενός καταχωρητή περιστρέφονται από αριστερά προς δεξιά, η σημαία κρατουμένου εισέρχεται στο MSB και το LSB εξέρχεται στη σημαία κρατουμένου. Με άλλα λόγια στη ROR η C μετακινείται στο MSB και το LSB μετακινείται στο C. Στην πραγματικότητα η σημαία C δρα σαν να είναι μέρος του καταχωρητή κάνοντας σε μέγεθος 9-bit τον καταχωρητή. Μελετήστε τον ακόλουθο κώδικα:

CLC                     ; make C=0 (carry is 0)
LDI  R20, 0x26          ; R20 = 0010 0110
ROR  R20                ; R20 = 0001 0011       C=0
ROR   R20               ; R20 = 0000 1001       C=1
ROR   R20               ; R20 = 1000 0100       C=1

Η εντολή περιστροφής ROL

ROL  Rd    ;   rotate Rd left through carry

Η άλλη εντολή περιστροφής είναι η ROL. Στην ROL τα bits μετατοπίζονται από δεξιά προς αριστερά και η σημαία C εισέρχεται στο LSB και το MSB εισέρχεται στη σημαία κρατουμένου C. Με άλλα λόγια στην ROL η σημαία C μετακινείται στο LSB και το MSB μετακινείται στο C. Δες το ακόλουθο απόσπασμα κώδικα. Ας το πούμε ξανά, η σημαία κρατουμένου δρα σαν να ήταν μέρος του καταχωρητή κάνοντας τον σαν 9-bit καταχωρητή.

SEC                        ; make C = 1
LDI  R20, 0x15             ; R20 = 0001 0101
ROL  R20                   ; R20 = 0010 1011   C = 0
ROL  R20                   ; R20 = 0101 0110   C = 0
ROL  R20                   ; R20 = 1010 1100   C = 0
ROL  R20                   ; R20 = 0101 1000   C = 1

Παράδειγμα

Γράψε ένα πρόγραμμα που να βρίσκει τον αριθμό των 1ς σε ένα δοσμένο byte

     LDI   R20, 0x97
     LDI   R30, 0              ; Ο αριθμός των 1ς
     LDI   R16, 8              ; Ο αριθμός των bits σε ένα byte

AGAIN:  
     ROR   R20      ;Δεξιά περιστροφή του R20 και η μεταφορά του LSB στη σημαία C
     BRCC  NEXT                ; Εάν C = 0 πήγαινε στην ετικέτα NEXT
     INC   R30                 ; Αύξηση του R30

NEXT:
     DEC   R16                 ; Μείωση του R16
     BRNE  AGAIN               ; Εάν ο R16 δεν είναι μηδέν πήγαινε στην ετικέτα AGAIN
     ROR   R20                 ; Άλλη μια φορά για να μείνει ο R20 ανεπηρέαστος
HERE:  JMP HERE                ; Σταμάτησε εδώ

Σειριακή μετάδοση δεδομένων

Κάποιες φορές απαιτείται η σειριακή μετάδοση δεδομένων, δηλαδή η μετάδοση ενός bit κάθε φορά από ένα πιν του μικροελεγκτή. Αυτό μπορούμε να επιτύχουμε με δυο τρόπους:
1] Χρησιμοποιώντας τη σειριακή θύρα. Με τη αυτοματοποιημένη χρήση της, ο προγραμματιστής έχει λιγότερο έλεγχο στη σειριακή μετάδοση δεδομένων. Ο τρόπος λειτουργίας της σειριακής θύρας περιγράφεται σε επόμενο κεφάλαιο.
2] Σειριακή μετάδοση δεδομένων με τη βοήθεια κώδικα που γράφουμε εμείς για να έχουμε τον έλεγχο της σειριακής μετάδοσης δεδομένων κατά την διάρκεια των εκπεμπόμενων παλμών και διαστημάτων.

Εντολές μετατόπισης δεδομένων:

Υπάρχουν τρεις εντολές για μετατόπιση δεδομένων μέσα σε καταχωρητες  GPRs του AVR. Αυτές είναι οι LSL, LSR και ASR

Η εντολή μετατόπισης LSL

   LSL  Rd    ; logical shift left

Στην LSL καθώς τα bits του καταχωρητή μετατοπίζονται από δεξιά προς αριστερά και το 0 εισέρχεται στο LSB καθώς και το MSB εξέρχεται και πηγαίνει στη σημαία κρατουμένου. Με άλλα λόγια στην εντολή LSL το 0 μετακινείται στο LSB και το MSB μετακινείται στη σημαία C.

Σημειώστε ότι αυτή η εντολή πολλαπλασιάζει τα περιεχόμενα του καταχωρητή με το 2 υποθέτοντας ότι η σημαία κρατουμένου C μετά την εντολή LSL δεν τίθεται σε 1. Μελετήστε τον ακόλουθο κώδικα:

     CLC                     ; make  C = 0  (carry is 0)
     LDI R20, 0x26           ; R20 = 0010 0110  (38)   C = 0
     LSL R20                 ; R20 = 0100 1100  (76)   C = 0
     LSL R20                 ; R20 = 1001 1000  (152)  C = 0
     LSL R20                 ; R20 = 0011 0000  (48)   C = 1
                             ; as C = 1 and content of R20 is not multiplied by 2

Η εντολή μετατόπισης  LSR

LSR  Rd    ;    logical shift right

Η δεύτερη εντολή μετατόπισης είναι η LSR. Με την LSR τα bits ενός καταχωρητή  μετατοπίζονται από αριστερά προς δεξιά. Το ψηφίο 0 εισάγεται στο MSB και το LSB εξέρχεται προς την σημαία κρατουμένου. Με άλλα λόγια με την εντολή LSR το ψηφίο 0 εισέρχεται στο MSB και το LSB μετακινείται στην σημαία κρατουμένου C. Σημειώστε ότι με αυτή την εντολή τα περιεχόμενα του καταχωρητή διαιρούνται δια δυο και η σημαία κρατουμένου περιέχει το υπόλοιπο της διαίρεσης. Εξετάστε τον ακόλουθο κώδικα:

    LDI  R20, 0x26                ; R20 = 0010 0110  (38)
    LSR  R20                      ; R20 = 0001 0011  (19)  C = 0
    LSR  R20                      ; R20 = 0000 1001  (9)   C = 1
    LSR  R20                      ; R20 = 0000 0100  (4)   C = 1

Η εντολή LSR δεν μπορεί να χρησιμοποιηθεί για διαίρεση προσημασμένων αριθμών δια του δυο.

Η εντολή ASR

ASR  Rd  ;  arithmetic shift right

Η τρίτη εντολή μετατόπισης είναι η ASR, η οποία σημαίνει αριθμητική μετατόπιση προς δεξιά. Με αυτή την μετατόπιση, δηλαδή με την ASR μπορούμε να κάνουμε διαίρεση δια του δύο στους προσημασμένους αριθμούς. Στην εντολή ASR καθώς τα bits του καταχωρητή μετατοπίζονται από αριστερά προς δεξιά, το MSB κρατείται το ίδιο και το LSB εξέρχεται προς το κρατούμενο C. Με άλλα λόγια το MSB δεν αλλάζει αλλά αντιγράφεται στο D6, το D6 μετακινείται στο D5, το D5 μετακινείται στο D4 κ.τ.λ. Μελετήστε τον ακόλουθο κώδικα:

      LDI   R20, 0xD0            ; R20 = 1101 0000 (-48)  C = 0
      ASR   R20                  ; R20 = 1110 1000 (-24)  C = 0
      ASR   R20                  ; R20 = 1111 0100 (-12)  C = 0
      ASR   R20                  ; R20 = 1111 1010 (-6)   C = 0
      ASR   R20                  ; R20 = 1111 1101 (-3)   C = 0
      ASR   R20                  ; R20 = 1111 1110 (-1)   C = 1

Παράδειγμα

Υπέθεσε ότι ο καταχωρητής R20 έχει τον αριθμό -6. Δείξε ότι ο LSR δεν μπορεί να χρησιμοποιηθεί για να διαιρέσει τον R20 δια δυο. Γιατί;

     LDI   R20,  0xFA         ; R20 = 1111 1010   (-6)
     LSR   R20                ; R20 = 0111 1101  (+125)
                              ; -6 divided  by 2 is not +125 and
                              ; the answer is not correct

Επειδή η εντολή LSR μετατωπίζει το bit προσήμου , αλλάζει το πρόσημο του αριθμού και επομένως δεν μπορεί να χρησιμοποιηθεί για προσημασμένους αριθμούς.

Παράδειγμα

Υπέθεσε ότι ο καταχωρητής R20 έχει τον αριθμό 48. Δείξε πως μπορούμε να χρησιμοποιήσουμε  την ROR για να διαιρέσουμε τον R20 με το 8.

                          ; to divide a number by 8 we can
                          ; shift it 3 bits to the right.
                          ; without LSR we have to ROR 3 times and
                          ; clear carry flag before each rotation
       LDI  R20, 0x30           ; R20 = 0011 0000  (48)
       CLC                      ;clear carry flag
       ROR  R20                 ; R20 = 0001 1000  (24)
       CLC                      ;clear carry flag
       ROR  R20                 ; R20 = 0000 1100  (12)
       CLC                      ;clear carry flag
       ROR  R20                 ; R20 = 0000 0110  (6)
                                ;48  divided by 8 is 6 and
                                ; the answer is correct

Η εντολή εναλλαγής SWAP

  SWAP Rd   ;    swap nibbles

Μια άλλη χρήσιμη εντολή είναι η SWAP, η οποία δουλεύει για τους καταχωρητές γενικού σκοπού από R0 έως R31. Η εντολή αυτή εναλλάσσει το χαμηλότερο nibble ενός καταχωρητή GPR με το υψηλότερο nibble. Με άλλα λόγια, τα χαμηλότερα 4 bits τοποθετούνται στα υψηλότερα 4 bits και τα υψηλότερα 4 bits τοποθετούνται στα χαμηλότερα 4 bits. Δείτε το ακόλουθο παράδειγμα:

Παράδειγμα

1] Βρείτε τα περιεχόμενα του καταχωρητή R20 στο ακόλουθο απόσπασμα κώδικα:

LDI   R20,  0x72
SWAP  R20

2] Αν δεν υπήρχε η εντολή SWAP πως θα μπορούσατε να εναλλάξετε τα nibbles; Γράψετε ένα μικρό πρόγραμμα που θα μπορούσατε να κάνετε αυτό.

Απάντηση

1]      LDI   R20, 0x72         ; R20 = 0x72 = 0b01110010
        SWAP  R20               ; R20 = 0x27 = 0b00100111

2]      LDI   R20, 0x72
        LDI   R16, 4
        LDI   R21, 0
BEGIN:
        CLC
        ROL   R20
        ROL   R21
        DEC   R16
        BRNE  BEGIN
        OR    R20, R21
HERE:   JMP   HERE