★ CODING ★ DEMONIAK ★ COURS d'ASSEMBLEUR par DEMONIAK ★ |
Cours d'assembleur par Demoniak - Partie 1 : Les bases de nombres | Coding Demoniak |
Partie 1 : Les bases de nombres On sait tous compter jusqu'à dix, cent, mille, dix mille... et même jusqu'à plusieurs millions... Pour comprendre ce qui va suivre, il faut faire la distinction entre les nombres et les chiffres. En fait, nous représentons les nombres en base dix. Pourquoi base dix ? Parce que nous utilisons 10 chiffres. Maintenant, imaginons qu'il n'y a que deux chiffres possibles, le 0 et le 1. Dans ce cas, on dit que l'on est en base deux, car seuls deux chiffres existent. Pour compter jusqu'à un, pas de problèmes, 0 puis 1. et maintenant le nombre deux ? Et bien, comme nous n'avons plus de chiffres disponibles, on va faire comme on faisait en base dix, on ajoute un chiffre devant et on recommence, ainsi, notre deux va se représenter 10. Et trois ? Et bien trois en base deux se représente 11. En fait, on augmente le chiffre le plus à droite. Lorsque celui-ci a atteint son maximum, il repasse à zéro (le premier chiffre de toutes les bases est le zéro) et on augmente le chiffre suivant à gauche. Si ce dernier a également atteint lui aussi son maximum, on répète l'opération : on le repasse a zéro et le chiffre le plus à gauche est augmenté, et ainsi de suite. Voici donc un exemple de représentation des seize premiers nombres en base deux : J'ai volontairement aligné les valeurs en base deux à droite, ce qui permet de bien voir que le chiffre le plus à droite est toujours augmenté, ensuite c'est le chiffre suivant à gauche, et ainsi de suite. Je me suis également volontairement arrêté à quinze, nous verrons pourquoi plus tard. Quelques termes à savoir : la base dix est appelée base décimale, ou plus couramment le décimal. La base deux est appelée base binaire, mais plus couramment le binaire. En gros, on peut comparer un microprocesseur à une ampoule, et l'information qu'il a à traiter à l'interrupteur qui commande l'ampoule. Quand on actionne l'interrupteur, l'ampoule s'allume. Quand on actionne l'interrupteur dans l'autre sens, l'ampoule s'éteint. L'ampoule travaille donc en binaire, elle ne connait que deux états, éteinte, que l'on peut faire correspondre à l'état zéro, et allumée, que l'on peut faire correspondre à l'état un. Et voilà que nous avons crée notre premier programme en language machine : l'allumage de l'ampoule ! Mais comment ils font pour traiter des grands nombres, les microprocesseurs ? Et bien, comme nous l'avons fait tout à l'heure dans notre exemple pour compter jusqu'à quinze en binaire, ils ajoutent des chiffres. Et c'est là qu'intervient la notion de 'bit'. Quoi ? Qu'est ce que c'est que ça ? Me direz-vous... Plutôt que de parler de chiffres, qui eux vont de zéro à neuf, on parle de bits pour la représentation des nombres en binaire. Donc, pour résumer, un bit est un élément qui prends la valeur 0 ou 1, et qui sert, lorsque l'on en associe plusieurs, à représenter des nombres en binaire. Et notre bon vieux Z80 étant un microprocesseur huit bits, cela signifie qu'il est capable de traiter des nombres représentés par un regroupement de huit bits. Mais ça va jusqu'à combien, un nombre de huit bits ? Plutôt que d'essayer d'écrire toutes les combinaisons possibles des huit bits pour arriver au maximum (qui sera représenté par 11111111), il existe des formules mathématiques simples pour connaître le nombre maximal représenté par un groupement de chiffres dans une certaine base. Si nous revenons en décimal, il est facile de savoir que l'on représente les nombres de zéro à neuf avec un chiffre (soit dix nombres différents), de zéro à quatre vingt dix neuf avec deux chiffres (soit cent nombres différents) et ainsi de suite. La formule mathématique pour le décimal est : 10 puissance nombre_de_chiffres. Par exemple, si nous utilisons quatre chiffres, on peut représenter : 10 puissance 4 = dix mille nombres, de zéro à neuf mille neuf cent quatre vingt dix neuf. Pour notre Z80, nous travaillons en binaire avec 8 chiffres (pardon bits), la formule nous donne : 2 puissance 8 = deux cent cinquante six valeurs, de zéro à deux cent cinquante cinq. On peut juste remarquer qu'un nombre de 16 bits aura une valeur maximale de... (Sortez les calculettes...) de 2 puissance 16 = 65536, soit de 0 à 65535, et que la représentation en binaire de sa valeur maximale (65535 donc) est : 1111111111111111 (soit seize 1). Pas très pratique comme représentation, n'est ce pas ? Heureusement, il y a un autre moyen de représenter des nombres que le binaire: l'hexadécimal. Qu'est ce que c'est encore que ce terme barbare ? L'hexadécimal est en fait le nom couramment employé pour la base 16. La base 16 est donc une base de comptage qui comporte 16 chiffres. les chiffres sont donc 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,... Et après ? Et bien, comme nous n'avons plus de chiffres, symboliquement parlant, pour continuer, on va piocher dans les lettres pour les six symboles qui nous manque, c'est à dire A, B, C, D, E, F. Si nous revenons à notre petit exemple du début, pour représenter les seize premier nombres en base 16 (hexadécimal), nous écrirons : Et le seize alors ? Et bien, comme pour toutes les bases, on représente le seize ainsi : 10 (avec le F du quinze, on repasse a zéro et on augmente le chiffre immédiatement à gauche). Si l'on étend cet exemple plus loin, et que l'on fait l'analogie avec les nombres en binaire, on remarque qu'il y a une relation directe entre le binaire et l'hexadécimal : un groupe de 4 bits sera toujours représenté de la même façon en hexadécimal. En plus, comme 4 bits peuvent représenter un maximum de 16 nombres, c'est exactement ce que peuvent représenter un chiffre hexadécimal ! Voici un exemple : Maintenant, pour plus de lisibilité, on ajoute à gauche les zéros non significatifs, et on sépare en groupe de 4 bits (ou un chiffre hexa...) On remarque donc une forte analogie entre l'hexadécimal et le binaire. Il est donc facile de faire des conversion hexadécimalbinaire. Ce qui semble plus compliqué que les conversions décimalbinaire. Allez, un petit exemple : 11011001 (binaire) en hexadécimal ... Bon, 1101, ca fait D en hexa et 1001 9, donc dans notre exemple, 11011001 fait D9 en hexa ! Un autre ? ok, convertissons : 11110011 (binaire) en hexadécimal... 1111 = F, 0011 = 3, soit F3 ! Une remarque importante, les codes hexadécimal (on préfère parler de codes que de chiffres, car ces 'codes'mélangent chiffres et lettres) peuvent être confondus avec du texte. C'est pourquoi, généralement, on ajoute un symbole devant un nombre hexadécimal, pour indiquer qu'il s'agit bien d'un nombre, et non d'un nom quelconque ! Ce symbole est en général le dièse (#) ou le 'et' commercial (&). Donc, nos deux nombres hexa des exemples précédents se représentent ainsi : #D9 ou &D9 et #F3 ou &F3. Pas trop compliqué pour l'instant ? Ok, on va corser un peu... Comment faire les conversions binairedécimal ? Pour convertir un valeur binaire en décimal, c'est assez simple. En fait, comme chaque chiffres binaire ne peut avoir que la valeur 0 ou 1, il suffit de donner un poids à chaque bit de notre nombre binaire. Ce poids sera de plus en plus fort au fur et à mesure que l'on va se déplacer dans les chiffres vers la gauche. Ainsi, le poids du chiffre le plus à droite est égal à 1, le poids du chiffre immédiatement à sa gauche 2, puis 4, puis 8, puis 16... En fait, il suffit de reprendre les puissances de deux (puisque l'on est en base deux) pour affecter le poids de chaque bits. Numéro du bit 7 6 5 4 3 2 1 0 On numérote les bits en général en commençant à zéro pour le bit le plus à droite, car on remarque que deux puissance zéro = 1 (poids) et ainsi de suite... (deux puissance 7 = 128) Le bit le plus à droite est aussi appelé bit de poids faible. Le bit le plus à gauche est quand à lui appelé bit de poids fort (car c'est lui qui a le plus gros poids...) Prenons un exemple, avec le nombre binaire %10110010. Numéro du bit 7 6 5 4 3 2 1 0 Et là, il suffit d'additionner les poids des bits non nuls, à savoir : 201 - 128 = 73 ( 201 contient 128, bit à 1 ) Voila, simple non ? Bon, oui, un peut complexe, mais en s'entraînant, ça devient vite facile, on retient les puissances de deux, et certaines conversions deviennent implicites. Pour la conversion décimalhexadécimal, c'est un peu plus compliqué, et je vous conseille de passer d'abord par une conversion décimalbinaire, puis une conversion binairehexadécimal, très facile. Maintenant que l'on sait comment le microprocesseur représente les nombres (en binaire), comment il fait pour calculer ? Et bien, le plus simplement du monde... 45 En binaire, c'est pareil, on a une retenue dès que l'on dépasse le plus grand chiffre possible soit 1. Exemple : %01001010 Si on décompose l'addition, on part de la droite vers la gauche. — Les deux premier chiffres, 0+0 = 0, facile. Ouf ! #4A Facile avec les conversion... Mais si nous faisons réellement l'addition, cela donne : Maintenant que nous savons faire quelques calculs en binaire et en hexa, voyons comment gérer les nombres signés. Oui, pour le moment, nous n'avons vu que des nombres positifs. Mais comment gérer les nombres négatifs ? En rajoutant le symbole '-' me direz-vous. Oui... Mais bon, n'oublions pas que nous allons travailler avec un microprocesseur, qui gère des nombres de 8 ou 16 bits (nous verrons cela plus tard), et qui doit pouvoir connaître le signe d'un nombre avec un moyen simple. C'est pour cela que l'on a inventé les nombres signées et les nombres non signés. Un nombre non signé, dison de 8 bits (un octet en fait), a sa valeur représenté par ces 8 bits. Un octet signé (un octet fait 8 bits), a sa valeur représenté par 7 bits seulement (les bits de poids le plus faible). Et le huitième bit ? Il sert de bit de signe. Evidement, en supprimant un bit pour la valeur, on ne peut plus aller que de 0 à 127. Et avec le signe ? Pour représenter -54, il faut donc positionner le bit de signe à 1. On pourrai penser que c'est aussi simple que cela, et que -54 donne %10110110, ou encore #B6. Pour cela, il suffit de complémenter (inverser) les bits de notre nombre, et ensuite de lui ajouter 1. Voici le détail : 54 : %00110110 #36 Pourquoi avoir ajouté 1 ? Et bien, dans le traitement des nombres positifs/négatifs, il y a un cas particulier à traiter. Le cas du zéro. Le zéro étant considéré comme positif, il est absurde de vouloir le représenter avec un signe négatif. Donc, comme les nombres positifs varient de 0 à 127, les nombres négatifs ne varient pas de 0 à -127, mais de -1 à -128. D'ou l'ajout de 1 pour la conversion nombre positif->négatif. -54 : %11001010 #CA On retrouve donc bien notre 54 ! Bon, on s'arrête là pour Aujourd'hui... Ces bases sont importantes pour la suite, n'hésitez pas à faire quelques exemples de conversions, de calculs sur papier, et de contrôler vos résultat avec, par exemple, la calculatrice de Windows...
|