NoTrace Security Forum

NoTrace Security Forum
Home | Discussioni Attive | Discussioni Recenti | Segnalibro | Msg privati | Utenti | Download | cerca | faq | RSS | Security Chat
Nome Utente:
Password:
Salva Password
Password Dimenticata?

 Tutti i Forum
 Problemi con il Computer
 Software
 come creo un programma?
 Forum Bloccato
 Versione Stampabile Bookmark this Topic Aggiungi Segnalibro
I seguenti utenti stanno leggendo questo Forum Qui c'č:
Pagina Precedente
Autore Discussione Precedente Discussione Discussione Successiva
Pagina: di 2

sisto
Starting Member



14 Messaggi


Inserito il - 01/09/2004 : 11:33:06  Mostra Profilo
Complemento a 2
Il complemento a 2 di un numero, e' uguale alla sua sottrazione da 2N, dove con 'N' si e' indicato il numero di bit impiegati per la rappresentazione del codice.
Il numero da complementare deve essere minore di 2(N-1)
Il complemento a 2 di 'A' e' simbolicamente indicato dall'apice 2 che precede la variabile 'A'; es: 2A
In definitava: 2A = 2N - A

Es:


Rappresentazione dei numeri a 8 bit: N = 8
2N = 28 = 256 = '1 0000 0000'
2(N-1) = 27 = 128 = '1000 0000'
I numeri da rappresentare in complemento a 2 devono quindi essere minori di 128, ossia <= '0111 1111'.
In realta' esiste un'eccezione.
Per il calcolo si procede nel modo indicato dalla definizione.
Es: sia A = '0110 1101' la configurazione binaria di cui si vuole calcolare il complemento a 2:

1 0000 0000 - (configurazione corrispondente a 28)
0110 1101 = (A)
-----------------
1001 0011 (2A = complemento a 2 di A)

Non e' affatto casuale che il complemento a 2 di un numero sia maggiore di 1 del complemento a 1 dello stesso numero.
Infatti 2N = '1 0000 0000' = '1111 1111' + 1
Quindi


2A = 2N - A = 100000000 - A =

= (11111111 + 1) - A = (11111111 - A) + 1 = 1A + 1

C.V.D. #
Uno dei metodi di rappresentazione di numeri negativi e' proprio la rappresentazione in complemento a 2, tramite la quale e' possible trasformare una sottrazione binaria in una somma.
Per esempio e' dimostrabile che la differenza

A - B
puo' essere sempre ricondotta alla somma

A + 2B
Analogamente la somma


A + (-B)
equivale alla somma

A + 2B
Il bit di peso maggiore o 'Most Significant Bit' (MSB) e' riservato al segno del numero rappresentato e' viene quindi chiamato bit di segno.
Il bit di segno = 1, indica che il numero e' negativo. Per risalire al numero rappresentato, e' sufficiente ricalcolare il complemento a 2 dell'intero numero (compreso il bit di segno).
Infatti vale la proprieta' che 2(2A) = A
Per convincersi: 2(2A) = 2N - (2N - A) = 2N - 2N + A = A


C.V.D. #
ECCEZIONE:
In precedenza ho detto che il valore del numero per cui calcolare il complemento a due deve essere < 2(N-1).
Cio' e' strettamente vero per la rappresentazione dei numeri positivi (che non devono essere complementati a 2), ma in realta' per la rappresentazione di un numero negativo e' ammesso il range fino a 2(N-1) compreso.
Ecco cosi' spiegato perche' un byte puo' rappresentare i valori compresi fra:

0..255 se trattasi di numeri interi senza segno.
-128..0..+127 se trattasi di numeri interi con segno.
Per lo stesso motivo una word (2 byte) puo' rappresentare i valori compresi fra:
0..65535 se trattasi di numeri interi senza segno.
-32768..0..+32767 se trattasi di numeri interi con segno.
Il vantaggio del complemento a 2 e' quello di velocizzare i calcoli effettuati dall'ALU (Aritmetic Logic Unit) posta all'interno della CPU (Central Processing Unit) nel calcolo delle differenze fra valori.
La rete di ingresso dell'ALU e' molto veloce ad effettuare il complemento a 1 dell'operando da sottrarre (sottraendo) eseguendo una negazione di esso, dopidiche' l'ALU effettua l'operazione di somma tra
il primo operando (minuendo)
la negazione del sottraendo
il valore '1' preventivamento inserito nell'ingresso del riporto (CI - Carry Input)






Confronti e sottrazioni
Nel Linguaggio Macchina 80x86 e' prevista l'istruzione CMP per eseguire confronti fra operandi di 8 o 16 bit.
L'istruzione CMP opera come SUB, cioe' esegue un'operazione di sottrazione senza, pero', modificare l'operando destinazione, ma con il solo effetto di modificare il registro dei flags.
Il test successivo di quali flag siano settati, completa l'operazione di confronto, con l'effetto di eseguire salti condizionati all'interno del codice macchina (o del programma assembler).

Di seguito, dopo una panoramica sulle convenzioni utilizzate si esaminano le diverse situazioni che possono capitare durante il confronto di operandi:

Operandi con segno (SIGNED)
Caso A=B
Caso A>B
Caso A<B
Operandi senza segno (UNSIGNED)
Caso A=B
Caso A>B
Caso A<B

Convenzioni utilizzate
Nel seguito ho utilizzato i seguenti simboli: Flag Nome Significato
CF Carry Flag 1 = Riporto per l'operazione successiva
BF Borrow Flag 1 = Prestito per l'operazione successiva
SF Sign Flag 1 = l'operando e' negativo
ZF Zero Flag 1 = l'operando e' nullo
OF Overflow Flag 1 = 'trabocco' del risultato
C Indica la colonna del Carry
S Indica la colonna del segno

N.B. - Sebbene che il BF non esista esplicitamente nel registro dei flags della CPU 80x86, l'ho voluto ugualmente prendere in considerazione per il fatto che nelle operazioni di sottrazione e di confronto, il CF assume il significato di BF.


N.B. - La condizione di overflow (OF=1) e' data dalla presenza di riporto sulla colonna del bit del segno o del bit del carry ma non in entrambe.
In altri termini non c'e' condizione di overflow (OF=0) se non c'e' riporto su nessuna delle due colonne, oppure se il riporto avviene su entrambe.


Qualche esempio potra' chiarire meglio le idee...


Esempio 1: Somma di 01010011 e 00110000


C S
111 (riga dei riporti)
0101 0011 + (1° operando)
0011 0000 = (2° operando)
---------------
1000 0011 (risultato)

In questo caso si verifica la condizione di Overflow, poiche' c'e' un riporto sulla colonna del bit di segno e non c'e' sulla colonna del bit di carry. Infatti interpretando gli operandi come signed, si avrebbe che 83+48=-125.
Interpretando la stessa operazione con operandi unsigned, il risultato sarebbe corretto: 83+48=131.

Esempio 2: Somma di 01010011 e 00101010


C S
1 (riga dei riporti)
0101 0011 + (1° operando)
0010 1010 = (2° operando)
---------------
0111 1101 (risultato)

La condizione di overflow non e' verificata, poiche' non ci sono riporti ne' sulla colonna del bit del segno, ne' del bit di carry.
Il risultato risulta sempre corretto, sia interpretando gli operandi signed che unsigned. Infatti si ha: 83+42=125.

Esempio 3: Somma di 10101101 e 11010000

C S
1 (riga dei riporti)
1010 1101 + (1° operando)
1101 0000 = (2° operando)
---------------
0111 1101 (risultato)

Il risultato e' affetto da Overflow, poiche' risulta che -83+(-48)=+125.
Infatti si ha riporto solo sulla colonna del bit di carry e non del bit di segno. Interpretando l'operazione con operandi unsigned, servono almeno 9 bit per rappresentare il risultato, poiche' il bit di carry e' posto ad 1.
In tal caso si avrebbe 173+208=381.

Esempio 4: Somma di 10101101 e 11010110

C S
1 1111 1 (riga dei riporti)
1010 1101 + (1° operando)
1101 0110 = (2° operando)
---------------
1000 0011 (risultato)

Il risultato non e' affetto da Overflow poiche' c'e' riporto sia sulla colonna del bit di segno che del bit di carry.
In questa situazione risulta che -83+(-42)=-125.
Interpretando gli operandi unsigned, per rappresentare il risultato occorrono 9 bit: 173+214=387.

Esempio 5: Somma di 10101101 e 00101010

C S
1 1 (riga dei riporti)
1010 1101 + (1° operando)
0010 1010 = (2° operando)
---------------
1101 0111 (risultato)

Il risultato non e' affetto da Overflow poiche' non c'e' riporto ne' sulla colonna del bit di segno ne' del bit di carry.
In questa situazione risulta che -83+42=-41.
Anche interpretando gli operandi unsigned, il risultato risulta corretto: 173+42=215.

Esempio 6: Somma di 01010011 e 11010110

C S
1 1 1 11 (riga dei riporti)
0101 0011 + (1° operando)
1101 0110 = (2° operando)
---------------
0010 1001 (risultato)

Il risultato non e' affetto da Overflow poiche' c'e' riporto sia sulla colonna del bit di segno che del bit di carry.
In questa situazione risulta che 83+(-42)=41.
Interpretando gli operandi unsigned, per rappresentare il risultato occorrono 9 bit: 83+214=297.

Operandi con segno

1° caso: Op1=Op2:
ZF = 1 (sempre !)

2° caso: Op1>Op2:
sign(Op1) = sign(Op2) ==> i due operandi hanno lo stesso segno.

Op1-Op2 > 0 ==> Op1+2Op2 = Op1+(2N-Op2) = 2N+(Op1-Op2) > 2N

==> CF = 1
BF = 0
OF = 0
SF = 0

sign(Op1) != sign(Op2) ==> i due operandi hanno segno diverso.

==> Op1 > 0 && Op2 < 0
Op1-Op2 > 0 ==> Op1-Op2 = Op1+|Op2| < 2N
==> CF = 0
BF = 1
OF = ?
SF = ?
==> SF = 1 ==> OF = 1
SF = 0 ==> OF = 0
==> SF = OF


3° caso: Op1<Op2:
sign(Op1) = sign(Op2) ==> i due operandi hanno lo stesso segno.

Op1-Op2 < 0 ==> Op1+2Op2 = Op1+(2N-Op2) = 2N+(Op1-Op2) < 2N

==> CF = 0
BF = 1
OF = 0
SF = 1

sign(Op1) != sign(Op2) ==> i due operandi hanno segno diverso.

==> Op1 < 0 && Op2 > 0
-(|Op1|+Op2) > -2N ==> 2N-(|Op1|+Op2) > 0
Op1-Op2 = 2N-|Op1|+(2N-Op2) = 2N+2N-(|Op1|+Op2) > 2N
==> CF = 1
BF = 0
OF = ?
SF = ?
==> SF = 1 ==> OF = 0
SF = 0 ==> OF = 1
==> SF = not(OF)

Operandi senza segno

1° caso: Op1=Op2:
ZF = 1 (sempre !)

2° caso: Op1>Op2:
Op1-Op2 > 0 ==> Op1+2Op2 = Op1+(2N-Op2) = 2N+(Op1-Op2) > 2N

==> CF = 1
BF = 0
OF = ?
SF = ?


3° caso: Op1<Op2:
Op1-Op2 < 0 ==> Op1+2Op2 = Op1+(2N-Op2) = 2N+(Op1-Op2) < 2N

==> CF = 0
BF = 1
OF = ?
SF = ?





Riepilogo in una tabella i risultati ottenuti precedentemente, assieme alle istruzioni assembler che permettono di eseguire il controllo sul verificarsi o meno delle condizioni:
Condizione Flag di controllo Istruzioni assembler
Operandi Signed Operandi Unsigned Operandi Signed Operandi Unsigned
Op1 = Op2 ZF=1 ZF=1 JE JE
Op1 != Op2 ZF=0 ZF=0 JNE JNE
Op1 > Op2 SF=0F e ZF=0 BF=0 e ZF=0 JG JA
Op1 >= Op2 SF=0F BF=0 JGE JAE
Op1 < Op2 SF!=0F BF=1 JL JB
Op1 <= Op2 SF!=0F o ZF=1 BF=1 o ZF=1 JLE JBE


Poiche' la CPU 80x86 non possiede il BF (flag del prestito), il risultato del flag CF viene negato. In tal caso il CF porta l'informazione del BF, quindi il CF non rappresenta piu' un riporto ma un prestito.
Pertanto in tabella andrebbe indicato CF al posto di BF.


Nelle operazioni di somma, invece, la CPU 80x86 considera il CF come flag di riporto.

Dualmente all'addizione, anche per la sottrazione esistono 2 istruzioni:

SUB Op1,Op2
Esegue Op1-Op2 ed il risultato e' posto in Op1.
SBB Op1,Op2
Esegue la sottrazione tenendo conto del prestito risultante dall'operazione precedente (tipicamente SUB o SBB).
L'operazione eseguita e' Op1-Op2-BF ed il risultato e' posto in Op1.
L'utilizzo di questa istruzione e' quello di poter eseguire sottrazioni a piu' di 16 bit.
A livello di CPU, l'istruzione SBB viene eseguita effettuando la somma fra:
il primo operando (minuendo)
la negazione del secondo operando (sottraendo)
la negazione del BF (flag di prestito)
Per spiegare questa relazione basta fare delle sempili considerazioni, ricordando il complemento a 2:


BF=0 ==> (Op1-BF)-Op2 = Op1+2Op2 = Op1+not(Op2)+1
BF=1 ==> (Op1-BF)-Op2 = Op1-1+2Op2 = Op1-1+not(Op2)+1 = Op1+not(Op2)

==> (Op1-BF)-Op2 = Op1+not(Op2)+not(BF)
un casinaccio



Torna all'inizio della Pagina

Gimli
Moderatore


Cittā: Belluno


1870 Messaggi

Inserito il - 01/09/2004 : 13:28:36  Mostra Profilo
quote:

Complemento ad 1
[blah blah blah...]


Ok, e allora? Che c'entra con la discussione?
Ciao

--
Prima di postare, leggere:
htt*://[www].notrace.it/Forum2/FAQ.ASP
htt*://[www].catb.org/~esr/faqs/smart-questions.html
Torna all'inizio della Pagina
Pagina: di 2 Discussione Precedente Discussione Discussione Successiva  
Pagina Precedente

 Forum Bloccato
 Versione Stampabile Bookmark this Topic Aggiungi Segnalibro
Vai a:
NoTrace Security Forum
© Nazzareno Schettino
RSS NEWS
Torna all'inizio della Pagina
Pagina generata in 0,31 secondi. TargatoNA | SuperDeeJay | Snitz Forums 2000