TUTORIAL ASSEMBLEUR - chapitre 1 Les bases indispensables pour débuter ------------------------------------- Définition de l'assembleur -------------------------- L'assembleur est un language de programmation transformant un fichier texte contenant des instructions, en un programme que le processeur peut comprendre (programme en language machine). Ce language machine a la particularité d'être difficile à programmer car il n'est composé que de nombres en héxadécimal (base 16). L'assembleur est une "surcouche" du language machine, il permet d'utiliser des instructions qui seront transformées en language machine donc il présente une facilité de programmation bien plus grande que le language machine. Le fichier texte qui contient ces instructions s'appelle le source. Le language héxadécimal ----------------------- Nous allons aborder un aspect très important de la programmation en assembleur : le système de numérotation en héxadécimal. Ce système est basé sur l'utilisation des chiffres et de certaines lettres de l'alphabet (de A à F). Vous connaissezbien entendu le système décimal (base 10). En assembleur, les nombres décimals sont suivis d'un "d" (1000=1000d) mais en principe la majorité des assembleurs calculent en décimal par défaut. Maintenant, prenons un système à base 5 (les 5 doigs de votre main). Nous allons compter en base 5. On commence par 0 (doigt 0), 1 (doigt 1), 2 (doigt 2), 3 (doigt 3), 4 (doigt 4). Problème..Comment faire pour représenter 5 ? C'est simple. Comme la base 5 nous permet de représenter des nombres avec les chiffres 0-1-2-3-4, on fait comme en base dix, on rajoute un 1 devant. Ce qui donne (doigt 5)=10 et (doigt 7)=12. En fait, quand on arrive à la fin d'un "cycle", on rajoute ou augmente le premier chiffre du nombre. Mais revenons à notre base 16. Nous allons faire la même chose que pour la base 5, cependant nous ne sommes plus limités dans la représentation (chiffre de 0 à 9). Nous arrivons à 9 (9d), maintenant comment faire le 10. Nous allons utiliser des lettres (10d=0A) et nous irons jusqu'à 15 (15d=0F). Nous ne pouvons pas utiliser le G et les lettres qui suivent, donc nous augmenterons le premier chiffre ce qui donne 16d=10. Continuez ainsi jusqu'à 255 qui fait FF. Et après. Et bien on continue. 256d=0100h (le h et le zéro qui précèdre indiquent que ce nombre est en hexadécimal). 257d=101h. 65535=FFFFh. Bon, je pense que vous avez compris. Pour convertir des nombres du décimal en héxa, vous pouvez utiliser la calculatrice de Windows en mode scientifique. Je vais finir mon explication avec le calcul binaire. Vous savez probablement que les ordinateurs calculent en base 2 (0 ou 1). Le calcul binaire consiste à mettre un 1 ou un 0 selon la valeur désirée. Chaque 0 ou 1 est appelé un bit, 8 bits forment un octet. Pour le nombre 1, nous avons 00000001b (le b signifie binaire). Un nombre binaire se décompose comme-ceci : 128|64|32|16|8|4|2|1 Pour le nombre 1, la première case est remplie (1=rempli). Pour avoir le nombre 2, nous aurons 00000010b et pour le nombre 3, nous aurons 00000011 (1 case=1 - 2ème case=1 => 1+2=3). Le nombre 11111111b donnera 255 puisque en additionant 1+2+4+...+128, on obtient 255. Plus il y a de bits, plus le nombre peut être grand, nous verrons plus tard qu'il existe différentes unités selon le nombre de bits. Le processeur et ses registres ------------------------------ Le processeur est composé de différentes parties. Les registres sont les éléments les plus importants du processeur pour celui qui programme en asm. Les registres sont souvent représentés comme des cases dans lesquelles sont stockés différentes valeurs de différentes tailles selon le type et le nom du registre. Il existe plusieurs types de registres : - registres généraux - registres d'états - registres de segment Nous allons nous intéresser aux registres généraux et aux registres de segment. On a plusieurs registres généraux qui commencent par A,B,C et D. Ces quatres registres sont les plus utilisés. Le 1er, AX (registre de 16 bits) qui se divise en deux petits registres de 8 bits, AL (l=low=bas) et AH (h=high=haut). Nous avons ensuite BX (BL et BH), CX (CL et CH) et DX (DL et DH), ces registres sont divisés comme AX en 2 parties hautes et basses. On peut rajouter un "E" devant les registres 16 bits afin d'obtenir un registre 32 bits. Ce qui donne EAX,EBX,ECX et EDX. Notez que l'on ne peut avoir de EAH ou ECL. La partie haute d'un registre 32 bits, n'est pas directement accessible, on doit utiliser différentes instructions afin de la faire "descendre" dans un registre de 16 bits et pouvoir finalement l'utiliser. Ces registres peuvent contenir une valeur correspondant à leur capacité. AX=65535 au maximum (16 bits) et AL=255 au maximum (8 bits). Je répète que la partie haute du registre 32 bits ne peut pas être modifiée comme un registre. Elle peut être modifiée seulement si l'on modifie tout le registre 32 bits (y compris la partie basse), ou par le biais de quelques instructions qui permettent de copier la partie basse du registre dans la partie haute, mais cela ne nous concerne pas pour l'instant. Les processeurs 286 et moins ne peuvent pas utiliser les registres 32 bits (EAX,EBX,ECX,EDX = impossible). Ce n'est qu'à partir du 386 que l'utilisation du 32 bits est possible. Pour terminer, je vais parler des registres pointeurs qui sont DI (destination index), SI (source index), BP (base pointer), IP (instruction pointer) et SP (stack pointer). Ces registres peuvent eux aussi être étendus à 32 bits en rajoutant un "E" (EDI,ESI,EIP,ESP,EBP). Ces registres n'ont pas de partie 8 bits, il n'y a pas de EDL ou de ESH. Les registres SI et DI sont le plus souvent employés pour les instructions de chaîne et pour acceder à des blocs en mémoire. Le registre SP est utilisé pour acceder à la pile. Nous ne l'employons presque pas, sauf pour du code très spécifique. Le processeur et ses registres de segment ---------------------------------------- Pour pouvoir chercher et placer des choses dans sa mémoire, un ordinateur a besoin de ce qu'on appelle une adresse. Celle-ci se compose de deux parties de 32 bits (ou 16 bits, cela dépend du mode employé). La première est le segment et la deuxième, l'offset. Voici un exemple : 0A000h:00000h (adresse de la mémoire vidéo) Dans cet exemple, il s'agit d'un adressage 16 bits. L'adressage 16 bits s'utilise en mode _réel_. Le mode réel est un état du processeur où il ne peut accéder à des blocs de taille supérieure à 16 bits (65536 bytes). Le 286 introduira un mode dit protégé qui permet de franchir cette barrière pour pouvoir accéder à quasiment tout la RAM en un bloc (ce mode protégé sera grandement amélioré à partir du 386). Nous nous contenterons du mode réel au début, car il est plus simple mais il présente tout de même des limites. Sur 386, les segments ont été conservés pour garder une certaine comptabiltié avec les vieilles générations de PC. Les registres de segment ne sont que lus et écris sur 16 bits. Le 386 utilise un offset de 32 bits (sauf en mode réel où il travaille toujours en 16 bits). Voici la liste de ces segments, ils sont au nombre de 6 : - CS (code segment) - SS (stack segment) - DS (data segment) - ES (extra segment) - FS (extra segment - seulement à partir du 386) - GS (extra segment - seulement à partir du 386) ### Chapitre 1 - dake / c a l o d o x ### ### http://www.space.ch/scene/calodox ###