Tips & Trick - Informatica

 

 

Complementi a 1 e a 2


1's complement

Il complemento a 1 (in inglese one's complement) di un numero binario è un metodo per codificare numeri con segno : i numeri positivi si esprimono secondo la struttura binaria naturale, per cui:

2dec = 00000010
127dec = 01111111

e i numeri negativi con il complemento a 1:

-2dec = 11111101
-127dec =
1000000

Il bit 7 è l' indicatore del segno (0= positivo, 1 = negativo)
Dal punti di vista strutturale il complemento a 1 di un numero binario N è:

 ~ N = 2n - 1 -N

L' impiego di un bit come segno fa si che i numeri rappresentabili vanno da ( 2n-1 - 1)  +(2n-1 - 1), ovvero, per un numero su 8 bit, da -127 a +127.

Dal punto di vista operativo, la realizzazione del complemento a 1 del numero, che è l' inversione dei bit che compongono il numero:

~ n = n ^ FFh

Vediamo lo stato dei singoli bit, che l' XOR con 1 va ad invertire:

Posizione nel byte 7 6 5 4 3 2 1 0
1E 0 0 0 1 1 1 1 0
~ 1E = E1 1 1 1 0 0 0 0 1

I PIC dispongono di un opcode specifico: comf, per cui:

comf n,d ; complemento a 1 di n nella destinazione d (W o il file n)

L'informazione del segno è contenuta nel valore stesso e questo permette di sommare valori positivi e negativi tra di loro direttamente. 
La somma di due numeri rappresentati in complemento a 1 dà il risultato corretto sommandogli il riporto; si ha overflow se i riporti generati nelle due posizioni più significative sono diversi. 
La sottrazione si effettua semplicemente sommando il complemento a 1 del sottraendo.

Una notazione in complemento a 1 ha, però, due aspetti di impraticità: il primo riguarda il fatto che lo zero può essere rappresentato sia come 00000000 (che è un numero "positivo") sia come 11111111 che è un numero "negativo"), fatto incongruo con l' aritmetica dove lo 0 non ha segno.
Il secondo punto riguarda la somma di due valori di segno opposto, dove  perché si deve tenere conto del riporto. 
Se vogliamo effettuare l' operazione a - b, essa è eseguibile come somma: a + (-b) = a + ~ b.

Ad esempio : 10 - 4 = 10 + (-4)
In binario:

10dec = 00001010
  4dec = 00000100    
per cui   ~4dec = 111110111

Allora:

            0000 1010 +
            1111 1011 =
          -------------
            1110 0101     
che è, considerando solo il nibble basso) 5 e non 6

Occorre considerare il riporto 1 e sommarlo al risultato per ottenere 10 - 4 = 6.


2' complement

La soluzione sta nell' uso del complemeno a 2 (in inglese two's complement), definizione usata anche per indicare l'operazione di negazione (inversione del segno).

In pratica, se il numero è positivo, il bit di peso maggiore sarà 0, che rappresenta il segno positivo, seguito dal numero sotto forma normale.  Ad esempio:

+ 10 → 01010 = 0 x (-24) + 1 x 23 + 0 x 22 + 1 x 2 + 0 x 2

Con n bit i numeri positivi rappresentabili vanno da 0 a 2n-1-1.  Così, su 8 bit si potranno rappresentare numeri da 0 a +127 (00000000 - 01111111).

Se il numero N è negativo, il bit di peso maggiore sarà 1, seguito dalla rappresentazione binaria di 2n-1+ N. Ad esempio:

- 5 → 1 x (-23) +  0 x 22 + 1 x 2 + 0 x 2

Con n bit i numeri negativi rappresentabili vanno da 0 a 2n-1.  Così, su 8 bit si potranno rappresentare numeri da 0 a -128 (00000000 - 10000000). 
Schematicamente:

binario :  0   1   2   3    125 126 127  128  129    253 254 255
          +---+---+---+-...-+---+---+----+----+--...-+---+---+
2's comp: 0   1   2   3    125 126 127 -128 -127    -3  -2  -1
          |------  positivi  -------|   |------ negativi -----|

Possiamo visualizzare meglio la situazione immaginando che i numeri siano disposti su una circonferenza:

binario:  128  129   253  254  255  0   1   2   3    125 126  127
           +----+-...-+----+----+---+---+---+---+-...-+---+----+
2's comp:-128 -127   -3   -2   -1   0   1   2   3    125 126  127

Il complemento a 2 consente di effettuare addizione e sottrazione senza la necessità di considerare il segno di un numero per determinare quale delle due operazioni sia necessaria; nell' hardware si utilizza il solo circuito sommatore, sia per l'addizione che per la sottrazione.
Infatti:

a - b = a + (-b)

Così 2-3 = 2 +(-3) = -1:

   2 = 00000010
+ -3 = 11111101
  ---- --------
  -1 = 11111111

e -2-3 = -2 +(-3) = -5

  -2 =    11111110
+ -3 =    11111101
  ----    --------
  -5 = 1  11111011

e 10-15 = 10 +(-15) =

   10 =    00001010
+ -15 =    11111101
  ----     --------
    5 = 1  11111011

Da notare la presenza di un riporto nelle ultime due somme, riporto utile per sequenze di più operazioni.


Il complemento a 2, in mancanza di una istruzione specifica nel set del processore, si realizza in diversi modi, ad esempio con un XOR:

- n = (n ^ FFh) + 1

Così, ad esempio, il complemento a 2 di 1Eh:

- 1Eh = (1Eh ^ FFh) + 1 =  E1 + 1 = E2

Altro sistema è usare una differenza :

- n = (FFh - n +1)

Così:

- 1Eh = FFh -1Eh + 1 =  E1 + 1 = E2

In effetti, la prima parte delle operazioni viste è la realizzazione del complemento a 1 del numero, che è l' inversione dei bit che compongono il numero:

~ n = n ^ FFh

per cui la negazione di un valore può essere effettuata con:

- n = ~ n + 1

In base a quanto detto, si potrà usare una semplice macro, che, però, è già presente nel set di pseudo opcodes supportati da MPASM:

NEGF  MACRO  file, dest
       comf
   file,1        ; comp. 1 di file in file
      
incf   file,dest     ; +1
     
ENDM

Va notato che il set di istruzioni del core a 16 bit (PIC18F) contiene l' istruzione nativa negf e quindi non richiede altre azioni.

Una alternativa:

       comf   file,w        ; comp. 1 di file in W
      
addlw  1             ; +1

e se il numero è già in W:

                 sublw  0             ; comp. 2 di file in W

Per PIC con core a 12 bit (Baseline) l' istruzione sublw  o addlw non esistono. Occorre adeguare con:

       addwf   file,w        ; W = W + file
      
subwf   file,w        ; W = file - W = file -(W + file) = -W

Nel caso di numeri a 16 bit occorre un piccolo algoritmo:

;------------------------------------------------- 
; Complemento a 2 di numero a 16 bit  
;-------------------------------------------------

; numero in aargb1 aargb0  
; risultato in aargb1 aargb0


compl16  comf   aargb1,f 
         comf   aargb0,f 
         incf   aaargb1,f 
         skpnz 
          incf  aargb0,f 
         retlw  0 


 

Copyright © afg . Tutti i diritti riservati.
Aggiornato il 21/03/15 .