L'ASSEMBLEUR - CHAPITRE 1 Par Nexxt

 

Introduction

Ce chapitre est le premier d'une (très) longue série, qui aura pour but de vous faire atteindre un très bon niveau dans la programmation en assembleur. Si j'ai entrepris d'écrire ce tutorial, c'est tout simplement parce que, pour cracker, il est indispensable de connaitre l'assembleur. De plus, il y a très peu de textes comme celui-ci, en français.
Je compte diviser le tutorial en une vingtaine de chapitres. Ceci implique qu'il ne faudra pas s'attendre à une diffusion rapide, car ces chapitres demandent de la rigueur, afin de ne rien oublier, donc beaucoup de temps pour les ecrire. Profitez de ce temps pour bien assimiler tout ce qui est dit, car à mon avis, vous ne pourrez pas passer au chapitre suivant sans avoir compris le précedent. C'est pour ça que j'essayerai au maximum de les organiser dans le meilleur ordre possible.
Ceci étant dit, si vous commencez à lire ce tutorial, je vous souhaite d'être persévérant pour aller jusqu'au bout. Si au cours d'un chapitre il y aurait une notion que vous ne ne comprenez pas: Nexxt@tipiak2000.com.

 

I- Rappel du système décimal

Je n'ai pas la prétention de vous apprendre ce qu'est le système décimal. Mais il est utile de rappeler quelques notions de base. Le système décimal utilise les chiffres de 0 à 9. C'est ce qu'on appelle un système de base 10 (par convention, on notera la base entre parenthèse à la fin du chiffre afin, par la suite, de ne pas confondre les décimaux des héxadécimaux). Un nombre peut être séparé en rang, et être exprimé avec des puissances de 10. Par exemple, le chiffre 6813 peut être décomposé ainsi:

rang (n) 3 2 1 0
chiffre 6 8 1 3

On a défini "n" comme le rang du chiffre. On peut donc exprimé le nombre avec des puissance de 10:
6813(10) = 6 x 103 + 8 x 102 + 1 x 101 + 3 x 100
6813(10) = 6000 + 800 + 10 + 3

Peut-être que cela ne vous apporte pas grand chose pour l'instant, mais ça pourrait être utile pour comprendre la suite.

 

II- Le système binaire

Comme vous le savez sans doute, les ordinateurs ne se représentent pas les nombre sous leur forme décimale, mais sous un forme "binaire". Le système binaire n'utilise que deux chiffres: 0 et 1. Le processeur comprend ces 2 chiffres grace à deux états différent définit par le standard TTL: 5V pour l'état haut (1) et 0V pour l'état bas (0). Le système binaire est donc un base 2, et peut être exprimé avec des puissances de 2. Il est assez facile de convertir un nombre binaire en nombre décimal. Prenons l'exemple de 1110111(2)

rang (puissance de 2) 64 32 16 8 4 2 1
chiffre 1 1 1 0 1 1 1

Le nombre peut donc s'écrire de cette façon:
(1 x 64) + (1 x 32) + (1 x 16) + (0 x 8) + (1 x 4) + (1 x 2) + (1 x 1) = 119(10)

La conversion binaire-décimal est donc relativement simple. Le contraire est plus contraignant. Prenons le nombre 5803(10).

Maintenant qu'on a les puissances de deux qui composent le nombre, on peut les mettre dans un tableau, et mettre un 1 en dessous, et un 0 pour celles qui ne sont pas utilisées.

rang (puissance de 2) 4096 2048 1024 512 256 128 64 32 16 8 4 2 1
chiffre 1 0 1 1 0 1 0 1 0 1 0 1 1

Le nombre binaire qui correspond à 5803(10) est 1011010101011(2).
Evidement il existe une infinité de multiples de 2 au-dessu de 4096. Cela implique donc que le nombre binaire comporte aussi une infinité de 0 au-dessus du dernier 1. C'est à dire que 1011010101011(2) et 00000000001011010101011(2) représentent le même chiffre. Alors, je vous pose la question: "on s'arrète ou?" Et là vous me répondez en toute logique: "Bah, après le dernier 1". Eh ben nan, même pas ça. C'est un petit peu plus compliqué, mais pas trop quand même.
Pour écrire des nombre décimaux long, il est préférable de les séparer par paquet de 3 afin de faciliter la lecture. Eh bien en binaire c'est la même chose, à ceci près qu'on les sépare par paquets de 4. Donc le nombre 1011010101011(2) va en fait s'écrire 1 0110 1010 1011(2). Mais là ou ça diffère encore avec les décimaux, c'est que les paquets doivent contenir 4 chiffres, ni plus, ni moins. Donc sur le nombre du dessus, il y a un 1 qui est tout seul. C'est la que vont intervenir les 0 supplémentaire. C'est donc la séparation en paquet de 4 qui va déterminer le nombre de 0 à ajouter. Le nombre va donc devenir 0001 0110 1010 1011(2).
Mais ceci est encore une vision simpliste du découpage des nombres binaires. Nous allons donc voir dans la partie suivante comment ils sont classé en fonction de la taille qu'on a défini.

 

III- L'organisation des données

Le nombre 1011010101011(2) est un nombre de 13 bits, ce qui est totallement arbitraire. Or les processeur 80x86 travaillent généralement avec des groupes de bits biens définis. Les plus courants sont les nibbles: 4 bits, les bytes (octets): 8 bits, les words: 16 bits etc... La suite vous apportera plus de précisions sur ces groupes.

Le bit

Le bit est la plus petite unité que l'on peut utiliser sur un ordinateur. En effet, il ne peut contenir qu'un chiffre. Il ne peut donc représenter que deux valeurs, le 1 ou le 0. Mais malgrès sa faible contenance, le bit peut représenter beaucoup de choses. Il peut vouloir dire oui ou non, noir ou blanc, tomate ou carotte, Pierre ou Marcel... enfin bref, il peut représenter tout ce que l'utilisateur défini, avec pour seule conditions, c'est que ce soit un choix entre deux choses, ou l'une est représentée par le 1 et l'autre par le 0.
Bien qu'un bit soit la plus petite unité, nous verrons par la suite qu'il n'est pas toujours facile de l'employer, et qu'il sera plus bénéfique d'utiliser un groupe de bits.

Le nibble

Le nibble est un groupe de 4 bits. Il est utile pour les valeurs décimales (encore appelées nombres BCD (binary coded decimal)) de 0 à 15, et pour les valeurs hexadécimales 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, F. En effet, la plus grande valeur que pourra contenir un nibble est "1111". Donc si l'on reprend la méthode de conversion vue plus haut:
(1 x 8) + (1 x 4) + (1 x 2) + (1 x 1) = 15(10) ou F(16)
La encore, son utilisation est assez limitée.
Le nibble est souvent utilisé pour représenter une valeur booléennes: vrai ou faux.

Le byte (octet)

Ca évidement, tout le monde sait ce que c'est. C'est un groupe de 8 bits. C'est de loin le groupement le plus utilisé en programmation. Pour les processeurs 80x86, l'octet est la plus petite structure adressable. C'est à dire qu'on ne peut commencer à stocker des valeurs en mémoire, et les utiliser avec un programme qu'a partir de l'octet, et pas en dessous. Pour utiliser des données plus petites que l'octet, il faut les stocker en tant qu'octet, et appliquer un masque afin de supprimer les bits superflus. Mais c une méthode contraignante. Vous voyez maintenant pourquoi l'utilisation du bit seul n'est pas aisée.
Les bits contenus dans un octets sont conventionnelement numérotés de 0 à 7, comme indiqué dans le tableau ci-dessous:

7 6 5 4 3 2 1 0
H.O nibble
L.O nibble

J'ai séparé ici l'octet en deux nibbles. Du bit 7 à 4, on appelle ça le H.O (High Order) Nibble, et du bit 3 à 0 c'est le L.O (Low Order) Nibble. Ceci afin de bien montrer le groupement par 4 des données.
Il peut représenter 28, soit 256 valeurs. On va donc utiliser l'octet pour représenter les nombres naturels de 0 à 255, ou les nombres signés (relatifs) de -128 à +127. La représentation des nombres signés fera l'objet d'une prochaine partie.
La plus importante utilisation des octets est pour les codes de caractère. En effet chaque caractère tapé au clavier à une valeur: de 0 à 127 pour les caractères de la norme ASCII (sont les caractères de bases comme les lettres et les chiffres), et de 128 à 255 pour les caractères étendus tels les caractères accentué, graphiques etc...
Vu que l'octet est la plus petite unité adressable, il sera plus facile de l'utiliser à la place des nibbles et des bits seuls. Donc il ne sera pas rare de voir la valeur booléenne représentée sous la forme "0000 0001(2)" pour vrai ou "0000 0000(2)" pour faux.

Les words (mots)

C'est un groupe de 16 bits, qui vont être numérotés de 0 à 15. Ils peuvent être divisés en deux octets de 15 à 8 et de 7 à 0:

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
H.O byte L.O byte

Ainsi qu'en 4 nibbles:

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
H.O nibble 3
nibble 2
nibble 1
L.O nibble 0

Une structure word peut représenter 216, soit 65 536 valeurs. C'est à dire les nombres naturels de 0 à 65 535, ou les nombres signés de -32768 à 32767. Son utilisation va être assez large, mais va surtout être utilisée pour les entiers, et les segments de mémoire (que j'expliquerai plus tard).

Les double words (doubles mots)

Comme son nom l'indique, ça va être une paire de word. Donc on reprend les schémas du dessus et on multiplie tout par deux. Je crois qu'il y a assez de choses à dire sur l'assembleur pour ne pas s'attarder sur les bases.
Une structure double word peut donc représenter 232, soit 4 294 967 295 valeurs, qui vont de 0 à 4 294 967 294 pour les nombres naturels et de  -2 147 483 648 à 2 147 483 647 pour les nombres signés.
La plupart du temps les structures double words sont utilisées pour le stockage des segments de mémoire.

 

IV- Le système hexadécimal

Le majeur problème du système binaire c'est que les nombres deviennent très vite assez long. Et il y a aussi le problème que dans la vie courante, à mon avis on aura plutot tendance à utiliser le système décimal, alors que les ordinateurs eux, utilisent le binaire. D'ou l'idée, pour palier à ce problème et contenter un peu les deux, de créer le système héxadécimal. Bien que ce mot commence par héxa, qui veut dire 6, le système héxadécimal n'est pas une base 6 mais une base 16. Pourquoi une base 16 et pas une base 17 ou 21? Tout simplement parce que la plus grande valeur qu'un nibble peut contenir est la valeur 15 (en partant de 0 biensur). Vous verez mieux pourquoi avec la suite.
En ce qui concerne la représentation de ces 16 valeurs, puisque les chiffres ne vont que jusqu'à 9, les lettres de A à F ont été ajoutées pour représenter les valeurs de 10 à 15. Les chiffres héxadécimaux vont donc de 0 à F.

Passons maintenant au problème des conversions. D'abord entre les hexadécimaux et les décimaux. C'est assez simple. C'est le même principe qu'entre le binaire et le décimal, sauf qu'ici on prend des puissances de 16 à la place des puissances de 2. Donc par exemple pour le nombre 2F5(16):

2 x 162 + F x 161 + 5 x 160 = 512 + 240 + 5 = 757(10)

Vous avez vu que pour les valeurs de 10 à 15 on utilise des lettres. Donc il n'est pas rare de se trouver face à des valeurs comme DEAD(16), BEEF(16), DEAF(16) ou FEED(16), qui sont bien réelles. Cela peut porter à confusion dans certains cas. Il y a aussi source de confusion entre les différent système. C'est pourquoi il faut adopter une convention d'écriture:

Maintenant voyons la conversion hexa-binaire et binaire-hexa. Elle est on ne peut plus simple. En fait, il suffit juste de connaitre ce tableau par coeur:

Binaire Hexadécimal
0000 0
0001 1
0010 2
0011 3
0100 4
0101 5
0110 6
0111 7
1000 8
1001 9
1010 A
1011 B
1100 C
1101 D
1110 E
1111 F

 

Pour convertir après c'est très simple. Dans un nombre binaire, il faut remplacer chaque groupe de 4 bits par sa valeur en hexa qui lui correspond. Et pour une valeur hexa, il faut remplacer chaque chiffre par les 4 bits qui lui correspondent. Par exemple pour le nombre 23FDh:

2 3 F D hexadécimal
0010 0011 1111 1101 binaire

Le nombre binaire sera donc 0010 0011 1111 1101b. C'est la même chose dans le sens contraire.

Il est vrai que des conversions décimal-hexadecimale ne sont pas faciles, ni les conversions décimal-binaire. Cependant, malgrès l'existance d'outil de conversion, il serait bon de connaitre le tableau des correspondances binaire-hexa par coeur, car il y aura beaucoup de ce type de conversion à faire, et vous verez par par la suite que ça va beaucoup plus vite de tête.

 

IV- Opérations arythmétique sur des nombres binaires et hexadécimaux

Avec les hexadécimaux, vous pouvez effectuer les même opérations arythnétiques qu'avec les décimaux (addition, division...). Je ne vais pas vous apprendre ici comment effectuer tout ça sur les hexa, ce serait fastidieux, vu la complexité de la chose. Je pense que si vous programmez beaucoup en assembleur, vous devez avoir à porté de main un calculatrice qui les fait pour vous. Il serait facile de vous convaincre de l'utilité d'un tel achat. Resolvez donc l'equation suivante:
9h + 1h = ?

Vous seriez tentés ici de mettre 10h. Mais non. La solution est 10, ce qui correspond en hexa à "0Ah", alors que "10h" est égal à 16.
Et là, ce n'est qu'un exemple excessivement simple.

Pour les nombres binaire, là aussi il faut une calculatrice, car la longueur des nombre fait qu'il y a trop de risque d'erreur. Ou si ça vous amuse vraiment de faire des calcul de tête, convertissez le nombre en décimal, fait l'opération en décimal, et reconvertissez le resultat en binaire. Mais c'est assez déconseillé.

 

VI- Opérations logiques sur les bits

Il existe 4 opérations logique que l'on pourra effectuer sur des hexa ou des binaires: AND, OR, NOT et XOR (OR exclusif). Contrairement aux opérations arythmétiques, il ne sera pas necessaire d'utiliser une calculatrice, les faire de tête sera beaucoup plus simple ici.

L'opérateur AND

L'opérateur AND, ne fonctionne qu'avec deux membres. Ces membres sont des bits simples. AND fonctionne selon la regle suivante:

0 AND 0 = 0
0 AND 1 = 0
1 AND 0 = 0
1 AND 1 = 1

On peut aussi représenter cela sous ça forme la plus courante, le tableau de vérité:

AND 0 1
0 0 0
1 0 1

Si on met le tableau en phrase celà donne: "Si le premier membre est 1 et le deuxième membre est 1, alors le résultat est 1. Sinon le résultat est 0". Si l'on pousse la réflection un peu plus loin, on peut dire que si le premier membre est 0 alors quelque soit le deuxième membre, le résultat est 0. Et si le premier membre est 1, alors le résultat et le deuxième membre sont identiques. Avec ceci, on peut donc forcer le résultat à être égal à 1 ou 0. Ce sont des considérations importantes pour la suite, lorsqu'on étudiera l'utilité de l'opérateur AND un peu plus tard.

L'opérateur OR-inclusif

L'opérateur OR ne fonctionne qu'avec deux membres aussi, selon la regle suivante:

0 OR 0 = 0
0 OR 1 = 1
1 OR 0 = 1
1 OR 1 = 1

On peut aussi représenter cela sous ça forme la plus courante, le tableau de vérité:

OR 0 1
0 0 1
1 1 1

Si on met le tableau en phrase celà donne: "Si le premier membre ou le deuxième membre ou les deux est 1, alors le résultat est 1. Sinon le résultat est 0". On appelle encore cet opérateur le OR-inclusif. Si l'on pousse la réflection un peu plus loin, on peut dire que si le premier membre est 1, alors le résultat est 1. Si le premier membre est 0, alors le résultat et le deuxième membre sont identiques.

L'opérateur XOR (OR-exclusif)

L'opérateur OR ne fonctionne qu'avec deux membres aussi, selon la regle suivante:

0 XOR 0 = 0
0 XOR 1 = 1
1 XOR 0 = 1
1 XOR 1 = 0

On peut aussi représenter cela avec le tableau de vérité:

XOR 0 1
0 0 1
1 1 0

Si on met le tableau en phrase celà donne: "Si le premier membre ou le deuxième membre, mais pas les deux est 1, alors le résultat est 1. Sinon le résultat est 0". On appelle encore cet opérateur le OR-exclusif. Si l'on pousse la réflection un peu plus loin, on peut dire que si un des membre est 1, alors le résultat est l'inverse de l'autre membre. Si l'un des membre est 0, alors le résultat et l'autre membre sont identiques.

L'opérateur NOT

L'opérateur NOT ne fonctionne qu'avec UN SEUL membre. Il obeit à la regle suivante:

NOT 0 = 1
NOT 1 = 0

On peut aussi représenter cela avec le tableau de vérité:

NOT 0 1
  1 0

 

VII- Opérations logiques sur les nombres binaire

Nous venons de voir que les opérateurs logiques ne fonctionnaient qu'avec des bits simples. Maintenant nous allons étendre la définition, et voir comment ils fonctionnent avec plus de bits.
Les processeurs 80x86 fonctionnent bit-à-bit, et non pas par chaine. C'est à dire que pour deux nombres binaires, il va d'abord prendre le premier bit de chaque, appliquer l'opération, inscrire le premier bit du résultat, passer aux deux suivants, etc... Par exemple, pour effectuer l'opération OR sur les nombres binaire 0110 1101 et 0001 1010, on procède colonne par colonne:

Binaire 1 0 1 1 0 1 1 0 1
Binaire 2 0 0 0 1 1 0 1 0
Résultat 0 1 1 1 1 1 1 1

On a vu que les opérations logiques ne pouvaient marcher qu'avec des nombres binaires. Donc dans le cas ou vous voudriez opérer dans une autre base, il faudrait impérativement convertir en binaire.

Nous avons vu dans les spécificités de chaque opérateur qu'il était possible de forcer un résultat. On peut faire de même avec une chaine de bits. Par exemple, on prend un nombre X de 8 bits, et on veut que les bits de 4 à 7 soient des 0. On a vu avec l'opérateur AND que si le premier nombre est 0, alors le résultat est 0, et que si le premier nombre est 1, alors le résultat est le deuxième nombre. Donc ici, pour changer les bits 4 à 7 en 0 il faudrait faire "X AND 0000 1111". On appelle ceci un masque.
De nombreux autres cas peuvent être démontré, je vous laisse y réfléchir.

 

VIII- Les nombres positifs et négatifs (ou signés)

Chose promise, chose due, nous allons maintenant voir comment sont représentés en binaire les nombre relatifs, encore appelé nombres signés (nombres qui ont un signe, pour les crétins). Pour cela nous allons prendre l'exemple d'un octet, soit 8 bits. Nous avons vu qu'un octet pouvait prendre 256 valeurs. Dans ces 256 valeurs, ils va donc falloir qu'on en laisse une partie aux nombres négatifs, c'est pourquoi on ne peut représenter que les nombres de -127 à 128 (ce qui fait toujours 256 valeurs).
C'est le dernier bit qui va déterminer le signe. Si c'est un 0, le nombre est positif, et si c'est un 1, il est négatif. Par exemple, si l'on reste avec notre octet:
0111 0110 est positif
0100 1100 est positif
1010 0011 est négatif
1110 0000 est négatif

Si on prend leur valeur en hexadécimal:
76h est positif
4Ch est positif
A3h est négatif
E0h est négatif

Pour convertir un nombre positif en son opposé il faut:
- appliquer l'opération NOT pour inverser tous les bits
- ajouter 1 au résultat

Par exemple 0000 1001 est l'equivalent binaire de 9:

0000 1001 9 en binaire
1111 0110 inversion des bits
1111 0111 +1

Maintenant on peut faire l'inverse pour retrouver 9 à partir de -9:

1111 0111 -9 en binaire
0000 1000 inversion des bits
0000 1001 +1

On retrouve bien le nombre 9 de départ.

Mais maintenant voyons un cas particulier. Avec un octet, la plus petite valeur négative qu'on pourra représenter sera -128. Si on fait la même chose avec cela donnera:

1000 0000 -128 en binaire
0111 1111 inversion des bits
1000 0000 +1

Bah ça c'est pas cool. Ca voudrait dire que -128 = -(-128) ! Mais en fait c'est plus simple que ça. En fait, la plus petite valeur négative n'a pas son équivalent positif, et ce, que ce soit pour un octet, un word ou autre chose... En effet, si on reste avec notre octet, la plus grande valeur positive que l'on va pouvoir représenter ce sera "0111 1111", soit 127. En effet, si le bit 7 ne peut pas être un 1, sinon ce serait un nombre négatif. Donc les valeur s'échelonnent de -128 à 127. C'est pour cette raison que -128 n'a pas son équivalent positif. Pour en avoir un, il fadrait élargir le nombre de bit, et passer à 16 bit par exemple. Dans un programme, si vous essayez de convertir le plus petit nombre négatif en nombre positif, le processeur vous répondra par une erreur du type "signed arithmetic overflow".

A ce stade vous êtes en droit de trouver ce système plus que complexe. Mais en réalité, avec ça, la plupart des opérations sont aussi simple qu'avec le système décimal. par exemple, si vous avez à faire 9+(-9), vous verez que tout se passe très simplement:

0000 1001 9 en binaire
1111 0111 -9 en binaire
1 0000 0000 resultat de l'add.

On se retrouve avec un 9eme bit, mais tous les autres sont des 0. Donc si on ne tient pas compte de ce bit supplémentaire, le résultat de 9+(-9) fait bien 0. Plus généralement, additionner une valeur positive avec sa correspondante négative tombe toujours juste. C'est à dire qu'on peut utiliser le même matériel pour les opération signées et non signées.

Vous n'aurez quasiment jamais à faire la conversion à la main. Le processeur le fera pour vous avec l'instruction NEG. Puis si vous avez besoin de le faire pour x raison, il y a tjrs la calculatrice. Mais il est toujours bon de savoir tout de même le faire à la main.

 

IX- Extension et contraction de chaines.

Les valeurs non signées

Vous savez que le processeur travaille avec des longueurs de chaines fixes (octets, mots etc...). Dans certains cas , il va être utile de faire des conversion entre ces chaines. Par exemple, prenons deux nombres de 8 bits: 1000 0110 et 1011 0111, soit les valeurs binaires des nombres 134 et 183. Leur addition donnera ceci:

1000 0110 134 en binaire
1011 0111 183 en binaire
1 0011 1101 resultat de l'add.

Le problème qui se pose là, c'est que le résultat fait 9 bits! Il ne pourra donc plus être contenu dans un octet. Cela provoquera fatalement une erreur. Pour y remédier, il faut que les valeur de départ aient 16 bits. Pour ça c'est très facile, il suffit de rajouter le nombre de 0 necessaire. On aura donc:

0000 0000 1000 0110 134 en binaire
0000 0000 1011 0111 183 en binaire
0000 0001 0011 1101 resultat de l'add.

Si on veut passer à des chaines plus petites, il faut s'assurer que les bits à supprimer sont tous des 0, sinon ça marche pas. Par exemple si pour le nombre binaire on passe de 0000 0100 1011 0010 à 1011 0010, on a plus du tout le même nombre. En décimal, on passe de 1202 à 178. Donc faites bien attention à ce type de conversion, c'est toujours délicat.

Les valeurs signées

Pour les valeurs signées ça reste aussi assez simple. Pour une extension, il suffit de copier la valeur du dernier bit dans tous les bits ajoutés. Exemple:
1000 1110 deviendra 1111 1111 1000 1110
0010 0011 deviendra 0000 0000 0010 0011

Pour la contraction là aussi il faut être vigilent. Il faut s'assurer que tous les bits qu'on veut supprimer sont identiques et egaux au dernier bit de la nouvelle chaine.

 

X- Décalage et rotation

Décalage

Un décalage (shift) consiste à décaler (ahah) tous les bits d'une chaine vers la droite (right shift) ou la gauche (left shift):

7 6 5 4 3 2 1 0
Left shift

Ici on a un décalage gauche. C'est simple. Mais la vous vous demandez surement ce qu'on met dans le bit 0, et ce qu'il advient du bit 7. Eh bien on va mettre un 0 au bit 0, et le bit 7 sort, et on ne s'en occupe plus.
Pour un nombre décimal, si l'on fait un shift left sur 01234 par exemple, on obtiendrait 12340, ce qui reviend à une multiplication par sa base: 10. Eh bien pour les binaires c'est la même chose. Left shift correspond à une multiplication par sa base: 2. Si vous le décalez deux fois, vous faite une multiplication par 2 x 2, donc 4. De façon général, si vous faites n décalages, vous multipliez par 2n.

7 6 5 4 3 2 1 0
Right shift

Pour le décalage droit, c'est un peu la même chose, sauf qu'ici le bit 0 est sortant.
On a vu que le left shift était l'equivalent d'une multiplication par deux, donc logiquement, le right shift est une division par 2. Enfin pour les nombres non signés, il n'y a pas de problèmes. Par contre pour les nombres signés il va falloir faire attention. On a vu que le dernier bit définissait le signe. Donc si on a un nombre négatif, et qu'on fait un left shift, c'est un 0 qui va être mis au bit 7, donc le nombre deviendra positif.
Si l'on veut se servir du right shift comme d'un diviseur, il va falloir introduire une nouvelle opération appelée "décalage droit arythmétique" (arithmetic right shift). Cette opération fera exactement comme un décalage droit, sauf que le dernier bit gardera la valeur qu'il avait avant. Dans cet exemple, si le bit 7 était un 1, eh bien après un décalage droit arythmétique il restera un, alors qu'avec un décalage droit il serait devenu 0.

Rotation

Une rotation (rotate) consiste à décaler là aussi tous les bits d'une chaine vers la droite (rotate right) ou la gauche (rotate left). Ce qui va le différencier de l'opération shift, c'est que le bit sortant va venir se placer de l'autre côté de la chaine. Par exemple dans une rotation gauche, c'est le bit 7 qui est sortant. Alors sa valeur va venir se placer au bit 0. Ici, tous les bits sont conservés, mais pas dans le même ordre.

 

XI- Les caractère ASCII

La table des caractère

Ce qu'il faut avoir en tête lorsque l'on parle des caractères, c'est qu'un caractère est codé sur 8 bits. Donc que 1 caractère est égal à 1 octet. Par exemple, si l'on prend un texte brut, c'est à dire sans formatage du texte, comme ceux fait avec le bloc note de windows, la taille de se fichier texte en octets représente donc le nombre exacte de caractères qu'il contient.
La table des caractères (sans les caractères étendus définis par IBM, donc les 128 premiers) est divisée en 4 groupes de 32:
Les 32 premiers (de 0 à 31) sont des caractères non imprimables. Il vont définir diverses opérations de disposition du texte (appelés caractères de controle), comme le retour à la ligne, le saut de ligne, le retour arrière, la tabulation, etc... Il n'ont aucune représentation graphique.
Le deuxième groupe (de 32 à 63) va contenir les caractères de ponctuations, le caractère d'espacement, et les 10 chiffres.
Le troisième groupe (de 64 à 95) contient les lettres majuscules et des caractères spéciaux
Le quatrième groupe (de 96 à 128) contient les lettres minuscules, des caractères spéciaux et le caractère de controle "delete"

Bien sur le jeu de caractère défini par IBM en contient 256. Ils vont être utilisés à des fins biens spécifiques, comme les caractère accentués etc...

M'enfin...

Il y aurait plein de choses à voir à propos des caractères ASCII, notament la relation en les majuscules et les minuscules, les chiffres, les groupes etc... Mais je ne pense pas que celà soit utile maintenant. Si vous êtes vraiment interessé et que vous voullez de plus amples explications, faites le moi savoir: Nexxt@Tipiak2000.com

 

XII- Conclusion

Normallement, si vous avez suivit la progression de ce chapitre vous devriez connaitre:

Cela fait déjà une bonne base pour commencer. Si vous connaissez déjà tous ça sur le bout des doigts, vous êtes bien parti. D'ailleur j'en profite pour vous rappeler qu'il est nécessaire de connaitre ce chapitre pour pouvoir passer au suivant.

 

LE CHAPITRE 2 SORTIRA EN FEVRIER 2000