Tutoriel 3 - Changement de base (rapide) et nombres signés

Pour discuter de l'assembleur
Anonyme2
Messages : 3518
Inscription : jeu. 22/janv./2004 14:31
Localisation : Sourans

Tutoriel 3 - Changement de base (rapide) et nombres signés

Message par Anonyme2 »

Code : Tout sélectionner

Tutorial 3 - Les changements de base, les nombres entiers signés
----------------------------------------------------------------

Par Oliv & Denis

- Terminé le 05 novembre 2004 -
-------------------------------


Les bases, suite :
------------------

Le changement de bases peut être très utile. Avant de voir les méthodes pour changer de 

bases, voici un tableau qui récapitule les 20 premiers chiffres des bases binaire, 

décimale, hexadécimale. 


____________________________________ 
| Binaire | Décimale | Hexadécimale | 
|___________________________________| 
|      0  |    0     |     0        | 
|      1  |    1     |     1        | 
|     10  |    2     |     2        | 
|     11  |    3     |     3        | 
|    100  |    4     |     4        | 
|    101  |    5     |     5        | 
|    110  |    6     |     6        | 
|    111  |    7     |     7        | 
|   1000  |    8     |     8        | 
|   1001  |    9     |     9        | 
|   1010  |   10     |     A        | 
|   1011  |   11     |     B        | 
|   1100  |   12     |     C        | 
|   1101  |   13     |     D        | 
|   1110  |   14     |     E        | 
|   1111  |   15     |     F        | 
|  10000  |   16     |    10        | 
|  10001  |   17     |    11        | 
|  10010  |   18     |    12        | 
|  10011  |   19     |    13        | 
|_________|__________|______________| 


Pour passer d'une base à l'autre, nous allons toujours revenir à la base décimale : 

Lorsque nous voulons passer de la base 2 à la base 16, on va faire base 2 => base 10 => 

base 16 

Conversion de la base 10 en une autre base X : 
---------------------------------------------- 

Méthode des divisions successives:
----------------------------------
Il faut diviser successivement le nombre à convertir par la base X puis noter le reste. 

Ensuite diviser le quotient par la base X puis noter le reste. Répéter ces opérations 

jusqu'a 0. Ensuite, pour obtenir le nombre dans la base X, il faut lire les restes de la 

dernière division à la première: 

Exemple: 
-------- 
(LSB =  Least significant bit soit bit le moins significatif, bit le plus à droite)
(MSB =  Most significant bit soit bit le plus significatif, bit le plus à gauche, appelé bit de poids fort)

Nous allons convertir 142 en binaire (base 2) : 
Pour la base 2, si le quotient est rationnel, on a un reste de 0 sinon on a un reste de 1 
142/2 = 71   donc 0 (LSB) 
71/2  = 35.5 donc 1 
35/2  = 17.5 donc 1 
17/2  = 8.5  donc 1 
8/2   = 4    donc 0 
4/2   = 2    donc 0 
2/2   = 1    donc 0 
2/1   = 0.5  donc 1 (MSB) 

Cela donne 142 en base 10 = 10001110 en base 2. 



Convertissons maintenant 1478 en hexadécimal (base 16) : 
1478/16 = 96 reste 6 
92/16   = 5  reste 12 
5/16    = 0  reste 5 
Or 12 en base 10 = C en base 16 
donc on a 1478 en base 10 = 5C6 en base 16. 



Conversion d'une base X en base 10 : 
------------------------------------ 

Pour passer d'une base X en base 10, il faut multiplier le nombre chiffre à chiffre par 

la base X à la puissance du poids du chiffre, chaque résultat sera additionné, le tout à l'envers, ce sera plus simple à travers un exemple: 

Nous avons 11010 en base 2 et nous le voulons en base 10, nous allons donc prendre le premier chiffre (0) que nous multiplions par 2^0 car c'est le premier. Ensuite nous allons ajouter 1*2^1 + 0*2^2 + 1*2^3 + 1*2^4 = 0 + 2 + 0 + 8 + 16 = 26. Donc 11010 en base 2 nous donne 26 en base 10. 

Autres exemples: 
---------------- 

On veut convertir C1DF5 qui est en base 16 vers la base 10: 
5*16^0 + 15*16^1 + 13*16^2 + 1*16^3 + 12*16^4 = 
     5 +     240 +   3328  +   4096 + 786432  = 794101 

On veut maintenant convertir 45601 qui est en base 8 vers la base 10: 
1*8^0 + 0*8^1 + 6*8^2 + 5*8^3 + 4*8^4 = 
    1 +     0 +   384 + 2560  + 16384 = 19329 


Les nombres signés :
--------------------
Un nombre peut se représenter sous sa forme binaire, décimale ou hexadécimale.
Bien souvent, c'est la représentation hexadécimale qui est utilisée car le nombre est codé sur une longueur 8 symboles ("8 chiffres").

Voici un nombre entier positif de type long (32 bits)

10001110010110100001110011111010 

et sa représentation en décimal  2388270330

et en hexadécimal  8E5A1CFA

On voit l'avantage du codage hexadécimal.

Pour un nombre de 32 bits, il y a 2^32 possibilités de valeurs allant de 
00000000000000000000000000000000  à  11111111111111111111111111111111


Pour des nombres positifs, ces valeurs vont de 
00000000000000000000000000000000  --> $00000000  --> 0 en décimal

à

11111111111111111111111111111111  --> $FFFFFFFF  --> 4294967295 en décimal


Nombres signés : Représentation d'un nombre négatif :
-----------------------------------------------------
Le résonnement suivant sur 32 bits est valable sur 16, 8 bits etc.

La solution pour stocker le signe est l'utilisation du bit b31 comme bit de signe.

B31 à 0 c'est un positif et à 1 c'est un nombre négatif.
Pour trouver un nombre négatif à partir du nombre positif, on inverse bit à bit et on ajoute 1

par exemple le nombre 20 codé sur 32 bits


00000000000000000000000000010100  --> +20

on inverse  bit à bit

11111111111111111111111111101011  

on ajoute 1

11111111111111111111111111101100  --> -20


Il s'agit du complément à deux qui est utilisé pour les calculs des entiers signés.
L'inversion simple bit à bit s'appelle le complément à un.



Pour résumer 

     11111111111111111111111111101011   est un nombre négatif
     |     
     | bit de
     | signe
     |
     01111111111111111111111111101011   est un nombre Positif


Le complément à deux d'un entier est la valeur positive qui permet d'obtenir 0 lorsque les deux valeurs sont additionnées.

Cette notion de nombre signé est très importante car en assembleur on effectue beaucoup de tests sur les valeurs des registres, mémoires, la pile etc.
Il existe une grande variété de tests, une partie servant pour les nombres non signés et une autre pour les nombres signés.
Purebasic n'utilise que des nombres signés. Si l'on écrit une librairie pour Purebasic, on peut utiliser les nombres signés ou non en fonction des besoins.
Un exemple simple pour expliquer ceci.

On a une liste chaînée ou une listview et on récupère le nombre d'éléments dans un registre et on compare à une valeur.
On peut très bien tester sur la base de nombres non signés car ces fonctions ne retournent jamais un nombre négatif. Il faut ne pas oublier quel type de nombre on manipule.


Le complément à deux fonctionne aussi pour trouver un nombre positif en partant d'un négatif.

Prenons la valeur décimale 1 codée sur 8 bits

    00000001

    11111110   on inverse bit à bit
    
   +00000001   on ajoute 1
   ----------
    11111111   --> -1
    
On part de ce nombre -1       
    
    11111111   --> -1

    00000000   on inverse bit à bit
    
   +00000001   on ajoute 1
   ----------
    00000001   --> 1
    
Pour trouver la valeur d'un nombre décimal négatif en binaire, on fait comme ceci :

Par exemple -37

En binaire 37 s'écrit  00100101

On inverse  11011010

on ajoute 1 -->  11011010

11011010 vaut donc -37

Maintenant, pour nous faciliter la vie, vous allez écrire en PureBasic un convertisseur décimal/binaire/hexadécimal prenant en compte les nombres signés ou non.
Avec une belle Interface et tout et tout (merci aux courageux). 

Les intervalles des nombres signés :
------------------------------------
Pour un nombre de 8 bits (un octet = un byte), on ne va utiliser que 7 bits pour coder la valeur absolue du nombre puisque le dernier bit (poids fort) ne sera qu'un indicateur de signe.
Ceci est vrai quelque soit le nombre de bits.

Byte  (8 bits)   -128 à +127 
Word  (16 bits   -32768 à +32767  
Dword (32 bits)  -2147483648 à +2147483647 
Qword (64 bits)  -9223372036854775808 à +9223372036854775807

On calcule les plages comme ceci

Exemple pour 16 bits :

Partie négative = -(2^15)   --> 15 bits sur les 16 pour la valeur absolue
Partie positive = (2^15)-1  --> on retire 1 car il faut bien que le 0 soit codé

Le cas du zéro :
----------------
    00000000

    11111111   on inverse bit à bit 
    
   +00000001   on ajoute 1 (pour le complément à deux)
   ----------
    00000000  --> 0


En complément à deux, le bit de signe du 0 est toujours 0. 0 n'a pas de représentation -0.
L'intervalle des positifs a autant de nombres que l'intervalle des négatifs sauf que l'intervalle des positifs commence à 0 tandis que celui des négatifs commence à -1.

L'intervalle sur 16 bits va de  -32768 à +32767  et non pas de -32768 à +32768


Voilà pour le troisième tut.
Merci à Oliv pour la partie de changement de base.


Prochain tut : Approche du fonctionnement d'un microprocesseur de la famille X86.
               

A+
Denis
Dernière modification par Anonyme2 le sam. 06/nov./2004 6:52, modifié 1 fois.
KarLKoX
Messages : 1191
Inscription : jeu. 26/févr./2004 15:36
Localisation : France
Contact :

Message par KarLKoX »

Tres bon tuto : bon sujet et bien expliqué #good
"Qui baise trop bouffe un poil." P. Desproges
Anonyme2
Messages : 3518
Inscription : jeu. 22/janv./2004 14:31
Localisation : Sourans

Message par Anonyme2 »

Merci KarLKoX :D

C'est pas toujours simple d'expliquer les choses.
minirop
Messages : 321
Inscription : mer. 02/août/2006 21:06

Message par minirop »

pour faire un passage 16 -> 2 ou 2-> c'est bcp plus facile de faire le passage directement.

5F1 donne :
5 => 0101
F => 1111
1 => 0001
donc
010111110001

et l'inverse :
0101|1111|0001
4+1|8+4+2+1|1
5|15|1
5|F|1
5F1

CQFD
Répondre