10. Πράξεις με προσημασμένους αριθμούς

Μέχρι στιγμής τα αριθμητικά δεδομένα που χρησιμοποιούσαμε παρίσταναν αριθμούς χωρίς πρόσημο. Όμως στη καθημερινή ζωή χρησιμοποιούμε θετικούς αλλά και αρνητικούς αριθμούς. Για παράδειγμα όταν αναφερόμαστε σε θερμοκρασία 5 βαθμούς Κελσίου κάτω από το μηδέν, αυτή παριστάνεται με την αρνητική τιμή -5, ενώ η θερμοκρασία 20 βαθμούς πάνω από το μηδέν με +20. Οι ηλεκτρονικοί υπολογιστές πρέπει να είναι ικανοί να διαχειρίζονται τέτοιους αριθμούς.

Ο τρόπος που χρησιμοποιείται για την αναπαράσταση προσημασμένων αριθμών είναι η δήλωση του περισσότερου σημαντικού ψηφίου (MSB) για την παράσταση του προσήμου. Αν το περισσότερο σημαντικό ψηφίο είναι 0 τότε ο αριθμός είναι θετικός και αν είναι 1 τότε ο αριθμός είναι αρνητικός.

Για τις τιμές ενός byte (8bit) το σημαντικότερο ψηφίο D7 χρησιμοποιείται για τη δήλωση του προσήμου. Εάν D7=0 τότε ο αριθμός είναι θετικός και εάν D7=1 ο αριθμός είναι αρνητικός. Για να κάνουμε αριθμητικές πράξεις με προσημασμένους αριθμούς χρησιμοποιούμε τους αρνητικούς αριθμούς σε αναπαράσταση συμπληρώματος ως προς δυο.

Για να μετατρέψουμε ένα θετικό αριθμό σε αρνητικό με την μέθοδο της αναπαράστασης συμπληρώματος ως προς δυο, θέτουμε το ψηφίο D7 στη τιμή 1 και στη συνέχεια αναστρέφουμε κάθε ένα από τα υπόλοιπα bit. Έπειτα προσθέτουμε στον αριθμό που προκύπτει την τιμή 1.

Παράδειγμα

Βρείτε την αναπαράσταση ως προς δυο για τον αρνητικό αριθμό -5

Ακολουθούμε τα ακόλουθα βήμα:
1]      0000 0101      η τιμή 5 στο δυαδικό σύστημα
2]      1111 1010      αναστρέφουμε κάθε bit
3]      1111 1011      προσθέτουμε το 1

Επομένως -5 = 0xFB  ο προσημασμένος αριθμός σε αναπαράσταση συμπληρώματος ως προς δυο για τον -5. Το bit D7 = N = 1 δηλώνει ότι ο αριθμός είναι αρνητικός.

Παράδειγμα

Βρείτε την αναπαράσταση ως προς δυο για τον αρνητικό αριθμό -0x34

Ακολουθούμε τα ακόλουθα βήμα:
1]      0000 0101      η τιμή 0x34 στο δυαδικό σύστημα
2]      1111 1010      αναστρέφουμε κάθε bit
3]      1111 1011      προσθέτουμε το 1

Επομένως -0x34 = 0xCC  ο προσημασμένος αριθμός σε αναπαράσταση συμπληρώματος ως προς δυο για τον 0x34. Το bit D7 = N = 1 δηλώνει ότι ο αριθμός είναι αρνητικός.

Το πρόβλημα της υπερχείλισης στις πράξεις με προσημασμένους αριθμούς

Όταν χρησιμοποιούμε προσημασμένους αριθμούς, μερικές φορές δημιουργείται ένα πρόβλημα που πρέπει να αντιμετωπιστεί. Αυτό είναι το πρόβλημα της υπερχείλισης. Ο μικροελεγκτής AVR δείχνει όταν έχουμε υπερχείλιση θέτοντας τη σημαία V της υπερχείλισης του καταχωρητή κατάστασης σε 1. Είναι στο χέρι του προγραμματιστή να διαχειριστεί το λάθος. Η CPU καταλαβαίνει μόνο bits 0 και 1 και της είναι αδιάφορο η σύμβαση θετικών και αρνητικών αριθμών. Τι είναι όμως η υπερχείλιση; Εάν το αποτέλεσμα μιας πράξης με προσημασμένους αριθμούς είναι μεγαλύτερο από την χωρητικότητα του καταχωρητή δημιουργείται υπερχείλιση και ο προγραμματιστής πρέπει να ενημερωθεί.

Παράδειγμα

Μελέτησε τον ακόλουθο κώδικα και ανάλυσε το αποτέλεσμα με τις σημαίες Ν και V

LDI   R20,  0x60    ;  R20 = 0110 0000  (+0x96)
LDI   R21,  0x46    ;  R21 = 0100 0110  (+0x70)
ADD  R20,  R21      ;  R20 = (+96) + (+70) = 1010 0110
                    ;  R20 = 0xA6 =-90 decimal,  INVALID

   +96      0110 0000
+  +70      0100 0110
-------   --------------
+166        1010 0110   N=1  (negative)  και  V=1,
                        sum = -90 (σε αναπαράσταση συμπληρώματος ως προς δυο)

Σύμφωνα με τη CPU το αποτέλεσμα είναι αρνητικό (Ν=1) το οποίο είναι λάθος. Η CPU θέτει V=1 για να δείξει το λάθος της υπερχείλισης.

Στο παραπάνω παράδειγμα ο αριθμός +0x96 προστίθεται στον +0x70 και το αποτέλεσμα σύμφωνα με την CPU ήταν -90. Γιατί; Ο λόγος είναι ότι το αποτέλεσμα ήταν μεγαλύτερο που θα μπορούσε ο R20 να περιέχει. Όπως όλοι οι άλλοι 8bit καταχωρητές ο R20 θα μπορούσε να περιέχει τιμές μικρότερες ή ίσες από +127. Οι σχεδιαστές της CPU δημιούργησαν μια σημαία υπερχείλισης ειδικά για αυτό το πρόβλημα για να ενημερώνει τον σχεδιαστή ότι το αποτέλεσμα μιας πράξης με προσημασμένους αριθμούς είναι λανθασμένο. Η σημαία Ν είναι ίση με το bit D7 του αποτελέσματος. Εάν Ν=0 το άθροισμα είναι θετικό (+) και εάν Ν=1 το άθροισμα είναι αρνητικό.

Πότε η σημαία V τίθεται σε 1;

Στις πράξεις με 8bit προσημασμένους αριθμούς η σημαία V γίνεται 1 σε μια από τις ακόλουθες περιπτώσεις:

1] Υπάρχει κρατούμενο από το D6 προς το D7, αλλά όχι έξω από το D7  (C=0)
2] Υπάρχει κρατούμενο από το D7 προς τα έξω (C=1) , αλλά όχι από το D6 προς το D7

Με άλλα λόγια η σημαία υπερχείλισης τίθεται σε ένα εάν υπάρχει κρατούμενο από το D6 προς D7 ή από το D7 προς τα έξω, αλλά όχι και τα δυο μαζί. Αυτό σημαίνει ότι εάν υπάρχει κρατούμενο όταν συμβαίνουν και τα δυο από D6 προς D7 και από D7 προς τα έξω, τότε V=0. Στο προηγούμενο παράδειγμα επειδή υπάρχει κρατούμενο μόνο από το D6 προς το D7 και όχι από D7 προς τα έξω, τίθεται V=1.

Παράδειγμα

Μελέτησε τον ακόλουθο κώδικα και ανάλυσε το αποτέλεσμα με τις σημαίες Ν και V

LDI    R20, 0x80     ; R20 = 1000 0000     (0x80 = -128)
LDI    R21, 0xFE     ; R21 = 1111 1110      (0xFE = -2)
ADD  R20, R21        ; R20 = (-128) + (-2)
                                ; R20 = 1000 0000 + 1111 1110 = 0111 1110
                                ; N = 0, R20 = 0x7E = +126,  invalid

-128                  1000 0000
+ -2                  1111 1110
------             -----------------
-130                  0111 1110                N =0 (θετικό)  και  V = 1

Σύμφωνα με την CPU το αποτέλεσμα είναι +126 το οποίο είναι λάθος και αυτό φαίνεται από τη σημαία V=1. Σημείωση: Εδώ η σημαία Ν δείχνει το πρόσημο του αλλοιωμένου αποτελέσματος και όχι του πραγματικού που θα έπρεπε να είχε.

Περισσότερα για τη σημαία V της υπερχείλισης

Στην εντολή πρόσθεσης ADD υπάρχουν δυο διαφορετικές περιπτώσεις. Οι αθροιζόμενες τιμές είτε έχουν το ίδιο πρόσημο είτε διαφορετικό. Όταν προσθέτουμε δυο τιμές με διαφορετικά πρόσημα, η απόλυτη τιμή του αποτελέσματος είναι μικρότερη από τους προσθετέους πριν την εκτέλεση της εντολής πρόσθεσης ADD. Έτσι δεν συμβαίνει υπερχείλιση όταν προσθέτουμε δυο αριθμούς με διαφορετικά πρόσημα. Υπερχείλιση είναι δυνατόν να έχουμε όταν προσθέτουμε δυο αριθμούς με το ίδιο πρόσημο. Σε αυτή την περίπτωση η απόλυτη τιμή του αποτελέσματος είναι μεγαλύτερη από τον κάθε ένα προσθετέο προτού εκτελέσουμε την εντολή ADD. Έτσι είναι πιθανό το αποτέλεσμα να είναι πολύ μεγάλο για τον καταχωρητή με αποτέλεσμα να έχουμε υπερχείλιση.

Εάν προσθέτουμε με την εντολή ADD δυο αριθμούς με το ίδιο πρόσημο, το αποτέλεσμα θα έχει το ίδιο πρόσημο με τους προσθετέους. Εάν προσθέτουμε δυο αριθμούς με το ίδιο πρόσημο και το πρόσημο του αποτελέσματος είναι διαφορετικό, τότε θα έχουμε υπερχείλιση. Με τον τρόπο αυτό η CPU γνωρίζει πότε θα θέσει τη σημαία V της υπερχείλισης. Εάν V=1 το αποτέλεσμα είναι λαθασμένο και εάν V=0 το αποτέλεσμα είναι έγκυρο.

Παράδειγμα:

Μελέτησε τον ακόλουθο κώδικα και ανάλυσε το αποτέλεσμα με τις σημαίες Ν και V

LDI  R20, -2                     ; R20 = 1111 1110  (R20 = 0xFE)
LDI  R21, -5                     ; R21 = 1111 1011   (R21 = 0xFB)
ADD  R20, R21                    ; R20 = (-2) + (-5) = -7 or 0xF9

    -2                 1111 1110
+   -5                 1111 1011
--------             ---------------
    -7                 1111 1001     and  V = 0   N = 1.  Sum is negative

Σύμφωνα με τη CPU το αποτέλεσμα είναι -7 το οποίο είναι σωστό και η σημαία V το δείχνει αυτό (V=0). Σε αυτό το παράδειγμα για τη σημαία V=0 διότι έχουμε κρατούμενο από τη θέση D6 προς D7 και από τη θέση D7 και έξω.

Παράδειγμα

Μελέτησε τον ακόλουθο κώδικα και ανάλυσε το αποτέλεσμα με τις σημαίες Ν και V

LDI   R20, 7          ; R20 = 0000 0111
LDI   R21, 18         ; R21 = 0001 0010
ADD   R20, R21        ; R20 = 0000 0111 + 0001 0010 = 0001 1001
                      ; R20 = (+7) + (+18) = +25, N = 0, positive
                      ; V = 0 correct

     +7                 0000 0111
+   +18                 0001 0010
----------           ----------------
    +25                 0001 1001        N = 0 (positive)  and  V = 0

Σύμφωνα με τη CPU το άθροισμα είναι ίσο με +25 το οποίο είναι σωστό όπως το δείχνει η σημαία V (V=0)

Ποια είναι η διαφορά μεταξύ των σημαιών Ν και S

Όπως είπαμε σε προηγούμενη ενότητα στους προσημασμένους αριθμούς η σημαία Ν παριστάνει το D7 bit του αποτελέσματος μιας πράξης. Εάν το αποτέλεσμα είναι θετικό η σημαία Ν είναι μηδέν και εάν το αποτέλεσμα είναι αρνητικό η σημαία Ν είναι 1.

Στις πράξεις με προσημασμένους αριθμούς μια υπερχείλιση είναι πιθανή. Η υπερχείλιση αλλοιώνει το αποτέλεσμα και αναστρέφει το bit προσήμου. Έτσι εάν προσθέσουμε δυο θετικούς αριθμούς στην περίπτωση της υπερχείλισης η σημαία Ν θα είναι 1 δηλώνοντας ότι το αποτέλεσμα λανθασμένα είναι αρνητικό. Η σημαία S δείχνει το πραγματικό πρόσημο μιας πράξης. Η CPU ελέγχει τη σημαία V μαζί με το bit D7. Εάν V=0 τότε δεν έχουμε υπερχείλιση και η σημαία S θα είναι η ίδια με το D7 για να δείξει το πρόσημο του αποτελέσματος. Εάν V=1 τότε έχουμε υπερχείλιση και η σημαία S είναι το ανεστραμμένο D7 bit δείχνοντας το πραγματικό πρόσημο του αποτελέσματος. Το bit S που ορίζει το πρόσημο του αποτελέσματος της πρόσθεσης προσημασμένων αριθμών είναι το αποκλειστικό OR των σημαιών Ν και V.