______ _______ ____ ______ / __ \ / _____/\ / \ \/ \_\ / /\_\ /\ / /\____\/ / /\ \/ /\ / / / /_/_/ / / /____ /\ / / /\__/ / / / / ____ / / _\___/ / / / / / \_\/ / / /_/\__/_/ / /______/ / /_/ / /_/ / \_\/ \_\/ \______\/ \_\/ \_\/ L'assembleur débutant ~~~~~~~~~~~~~~~~~~~~~ Cette série d'articles à pour but de familiariser les non-pratiquants assembleurs à cette science biscornue. Pour une personne qui a déjà programmé dans un langage évolué (BLITZ,GFA,AMOS,C,PASCAL) le passage risque d'être douloureux car les commandes toutes faites n'existent plus. Pour les autres, ceux qui n'ont jamais programmé de toute leur vie, ça va être très douloureux. Quoi qu'il en soit, ne désespérez pas car qui veut apprendre l'assembleur doit avoir de la patience et du courage. Cependant, c'est à la portée de tous. Ces cours ont pour objectif premier de conduire à la confection de démos. Ils ne sont en aucuns cas un plagiat de la Bible de l'Amiga. Celle ci est malheureusement trop souvent obscure sur certain points et ne s'adresse pas aux débutant mais aux programmeurs initiés. Toutefois, il sera utile par la suite d'avoir la Bible à ses cotés. ~~~~~~~~~ Cours n°1 ~~~~~~~~~ Le Hardware ~~~~~~~~~~~ Pour bien programmer un Amiga, il faut comprendre comment ça marche. Nous allons visiter l'architecture de la machine et expliquer comment fonctionnent ses différents organes. Les gens qui ont déjà pratiqué un peu l'assembleur peuvent lire ces lignes d'un oeil léger. Les circuits principaux ~~~~~~~~~~~~~~~~~~~~~~~ I Mémoire ~~~~~~~~~ I.1 Généralités L'Amiga (le 1200 de base) est pourvu de 2 mégas octets de mémoire continue. Ce qui veut dire en matière d'adresse que l'on débute à 0 et que l'on termine à 2097151 ($1FFFFF). L'élément de base de la mémoire est l'octet. Donc imaginez une étagère géante avec 2 millions de petits casiers avec dans chacun de ces casiers un nombre compris entre 0 et 255. L'adresse mémoire correspond au numéro du casier. I.2 Le binaire Avant de continuer, nous allons faire une petite parenthèse sur les modes de comptage. Vous êtes sûrement habitué depuis toujours à compter en mode décimal, c'est à dire en base 10. Malheureusement en électronique on ne connait que deux états, le 0 ou le 1. Donc le système de comptage le plus simple que connaisse un ordinateur est le système binaire. On ne compte plus pour les unités de 0 à 9 mais de 0 à 1. Cela donne: Décimal: |0 |1 2| 3| 4| 5| 6| 7| 8| 9| 10| Binaire: |0 |1 10| 11| 100| 101| 101| 111| 1000| 1001| 1001| ........................................................ ........................................................ | 251| 252| 253| 254| 255| | 11111011| 11111100| 11111101| 11111110| 11111111| Chaque "1" ou "0" s'appelle un "bit". "11111111" est un nombre huit bits. Le nombre huit bit ("octet") a été pris comme base pour les ordinateurs individuels de la première génération comme par exemple l'excellent Commodore 64. Le processeur ne pouvait manipuler que des nombres compris entre 0 et 255. Cette convention est restée comme base mais les processeurs actuels manipulent des nombres beaucoup plus important en taille. Le système binaire ne nous est pas familier, cependant il existe une façon simple de compter en binaire. Pour cela, il faut retourner aux sources des systèmes de comptage. Voici l'explication à travers quelques exemples: En décimal, 1995 s'écrit en fait comme: (le ° signifie puissance) 1*(10°3) + 9*(10°2) + 9*(10°1) + 5*(10°0). La base 10 est portée aux - - - - puissances successive qui sont 1, 10, 100, 1000, 10000, 100000... ce qui donne 1*1000 + 9*100 + 9*10 + 5*1 = 1995. - - - - ---- En binaire, c'est la même chose par exemple 00110011 s'écrit en fait: 0*(2°7) + 0*(2°6) + 1*(2°5) + 1*(2°4) + 0*(2°3) + 0*(2°2) + 1*(2°1) + - - - - - - - 1*(2°0) - Les puissances de deux ne sont pas aussi faciles que celles de 10 mais elle sont quand même mémorisables: 2°0=1 \ 2°1=2 | 2°2=4 | 2°3=8 | 2°4=16 | Contenus dans un octet. 2°5=32 | 2°6=64 | 2°7=128 / (2°8=256) Je suis désolé pour vous mais vous devez connaître ces quelques puissances par coeur et les ressortir sans hésitation. Dans notre exemple 00110011, les puissances de deux sont soient multipliées par 0 ou par 1. Donc simplement on additionne ces puissances : Bit n°7 \ /Bit n°0 0 0 1 1 0 0 1 1 32 + 16 + + 2 + 1 = 51 Vous devez être capable de sortir la valeur de la puissance suivant le numéro du bit (de 0 à 7). Cela vous permettra de transcrire les petits nombres binaires en décimal sans calculatrice. Ca aide énormément! Le bit 0 est appelé dans notre cas le bit de poids faible car sa puissance de deux ne vaut que 1. Le bit numéro 7 est appelé logiquement le bit de poids fort car... Bon vous avez compris sa puissance de deux est 128. On a aussi des petits trucs mécaniques du genre si le dernier bit (le n°0) est à "0", le nombre en question est paire. Ou alors si j'ai 11111011 , c'est 255-4 cad 251... Vous voila des as en binaire... C'est la base, mais on utilise pour les grand nombres un autre système, beaucoup plus maniable. En fait c'est du binaire mais on regroupe les bits par paquets de 4. Et la ,combien ça fait 1111 en binaire ? Vous avez 30 secondes.... Bon fini! Ca fait 15 ce qui implique 16 possibilités (ne jamais oublier le zero!). On utilise donc un système en base 16 ... L'hexadécimal... I.3 L'hexadécimal On veut neanmoins garder une ecriture coherente, c'est a dire garder les unités sur un seul caractere or 10..11..12..13..14..15 sont sur deux caracteres. On utilise pour remplacer A...B...C...D...E...F. Donc si on compte en hexadécimal, on obtient : 0 1 2 3 4 5 6 7 8 9 A B C D E F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 ... ETC ... On converti facilement du binaire en hexadécimal avec les paquets de 4 0 1 2 3 4 5 6 7 8 9 A B C D 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 E 1111 Vous devez connaître ces codes par coeur... dur ... il a pas de chance le monsieur ... Pour en revenir à notre exemple de tout à l'heure "00110011" s'écrit 33 en hexadécimal. On peut compter directement en hexadécimal pour des petits nombres. Par exemple 33 correspond à 33*16 + 3. Par contre si on avait eu EC en hexa il faudrait faire de tête 14*16 + 12 . C'est déjà moins cool. Voila,vous connaissez maintenant trois systèmes de comptage. Alors si je vous dit combien fait "11" ? Vous me repondez aussitôt "Mais dans quel système ?" et c'est une remarque pertinante! Pour tout ceux qui ont repondu "Ben ca fait Onze! Il est con lui". J'accepte aussi. :) Pour éviter tout mélange on écrit les nombres avec une sorte d'identificateur. Le % correspond au binaire et le $ à l'hexadécimal. Pour le décimal, on utilise rien. Donc 10 c'est Dix ... %10 c'est Deux et $10 c'est Seize... Ok ? (il existe aussi la notation 88H (= $88). Elle est utilisée par certains assembleurs notemment avec des processeurs INTEL par exemple.) I.4 Représentation de la mémoire En général, une adresse est écrite en hexadécimal, son contenu aussi d'ailleurs. Si on desassemble une partie de la mémoire à l'adresse $20000 par exemple on y verra : ___ $FF = 255 , valeur maximum. / 00020000 00 1F 00 24 22 00 00 00 FF 59 11 FF 00 FF 01 02 00020010 00 01 50 56 45 89 45 BF 0F C5 00 E0 A0 44 05 44 | | Adresse valeurs Ce qui veut dire en clair que dans la case $20000 il y a $00 ... dans $20001 il y a $1F .... $20002 il y a 00 ... $20010 il y a $00 ...... (Ces valeurs sont aléatoires...on peut trouver n'importe quoi à cette adresse bien sur....) Souvenez vous bien qu'une représentation d'un octet en hexadécimal est de la forme $XX ... Donc c'est exactement ce que l'on voit ici. Un petit point au passage: ne confondez pas "Byte"("Octet" en anglais) avec "Bit". C'est tout merci... I.5 Differents types de mémoire La mémoire de base du 1200 est la mémoire "Chip". Il existe aussi de la mémoire "Fast" qui comme son nom l'indique est plus rapide. Cependant son organisation est strictement conforme à tout ce que je viens de dire, paniquez pas! Ses adresses sont seulement plus hautes et c'est ce qui lui impose quelques contraintes d'utilisation que nous verrons un peu plus loin. I.6 L'Ascii Pour en finir avec ce chapitre nous allons parler de l'ascii (prononcé "à Ski."). C'est aussi une représentation possible de la mémoire. En fait le code ascii existe depuis des lustres. L'ascii est une manière de coder l'écriture, par exemple ce texte est en ascii. Dans le code ascii, un caractère est codé sur un octet. Donc chaque caractère peut prendre une valeur de 0 à 255 comme nous avons vu plus haut. Des félés se sont amusés, il y a quelques dizaines d'années, à faire correspondre à toutes ces combinaisons des lettres, chiffres et différents symboles. Cette convention est restée et l'Ascii est utilisé partout. Voici quelques codes : $61 = "a" $62 = "b" $63 = "c" $20 = espace ...etc ...etc On peut trouver facilement la table de correspondance hexa>ascii et vice et versa. --------------------------------------------------------------------- II Processeur et autres circuits ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ L'élément le plus important de l'Amiga est bien sur le 68020 (le processeur). Même si ce n'est pas lui qui fait entierement toutes les opérations, il en réalise une bonne moitié et commande le reste. II.1 Le processeur L'organe le plus important relié au processeur est la mémoire. Ce dernier a la possibilité de lire ou d'écrire chacune des cases de la mémoire. L'opération la plus simple effectuée par le proc (prononcez "Prosse" si vous voulez être branché!) est l'opération de deplacement de cases. Toutes les operations possibles seront expliqué par la suite ne vous inquietez pas. Le proc possède neanmoins sa propre "mémoire". Entendez par là simplement qu'il possède quelques cases bien à lui contenu dans son petit boitier. Ces cases s'apellent des registres. Pour l'instant, retenez simplement que le processeur possède ses propres cases. La notion d'interruption sera trés importante par la suite. On appelle interruption un petit signal reçu par le proc. Ce signal peut être reçu à tout moment. Le proc est prevenu au moment où le signal arrive, il sait aussi d'où ce signal provient. Pour le moment, une interruption sera pour nous une personne qui frappe à la porte du proc. On vera par la suite les différents types d'interruptions et comment on s'en sert. II.2 Les circuits auxillaires II.2.1 Les registres $DFFxxx Il existe une zone mémoire assez particulière. Elle n'existe pas physiquement, c'est pour cela que je n'en ai pas parlé dans la première partie. Il s'agit de toutes les adresses de la forme $dffxxx. Il s'y trouve une petite centaines de cases ou plutôt une petite centaine de registres. Attention ces registres là n'ont rien a voir avec ceux du processeur (il y en a environ 16 dans le proccesseur). Ces registres ont pour fonctions de definir et de piloter un bon nombre d'elements de l'Amiga. Par exemple c'est par l'intermediaire de ces registres que l'ont defini la palette de couleurs, la résolution de l'écran, la taille de l'écran ou que l'on joue des sons ... II.2.2 Les Dmas Dma signifie Direct Access to Memory (Accés directe à la mémoire). Il en existe environ 9. Un Dma est une sorte de canal qui peut lire une zone de mémoire de facon autonome. En clair, c'est un "Oeil" qui se promène tout seul dans la mémoire. Par exemple pour les Dma sons, on indique où se trouve le début d'un son, sa frequence, son volume et tuti quanti. Le Dma se charge de lire ce son et de le balancer sur la sortie son de l'Amiga. Une fois que le processeur a initialisé un Dma, il redevient disponible et peut faire d'autre choses. On retrouve ainsi un Dma pour les disks, un pour le blitter, quatres pour le son, un pour le copro, un pour l'écran et un pour les sprites. Ces Dma sont tous initialisés pas le biais de registres $DFFxxx. II.2.3 Le Blitter Le blitter est un organe qui particularise notre bel Amiga. Le blitter est un circuit qui realise quelques operations fort sympathiques. Il est capabale par exemple de copier des données d'une zone mémoire vers une autre, de tracer des lignes ou de remplir des surfaces. Son activité est parallèle avec celle du proc. Si le proc ordonne au blitter (par le biais de quelques registres $dffxxx.) de copier une zone mémoire assez importante cela se passera de la facon suivante: Le proc initialise le blitter qui démarre sa copie de bloc mémoire. Le proc est ensuite libre de faire ce qu'il veut pendant que le blitter copie ses données. C'est-y pas beau ca ? C'est une ébauche de vrai multitâche non ? II.2.4 Le Copper Le copper est un circuit specialisé au même titre que le blitter. Il n'existe que sur les architectures Amiga. Décidement l'Amiga est vraiment une belle machine (!). Alors qu'est-ce que fait le copper ? Et bien comme j'ai vu que la rubrique "Algorithme" organisait des concours, je vais en faire aussi. Alors la question est : "A quoi sert le Copper ?" , j'attend vos reponses , ecrivez vite... Nannn, je déconne. Le copper ne réalise concrètement que deux opérations. Il peut attendre et il peut mettre des choses dans les registres $DFFxxx. Le copper est synchronisé avec le faisceau d'électrons. C'est à dire que l'on peut attendre le moment où le faisceau d'électrons arrivera à un endroit précis de l'écran. Je vous rappelle pour mémoire qu'un faisceau d'électrons percute votre tube cathodique de l'interieur pour faire apparaitre de beaux pixels de toutes les couleurs. Ce faisceau se deplace de gauche à droite et de haut en bas. Donc le Copper ça parrait bête mais c'est génial. On communique au debut de notre programme une liste d'instruction composée de Wait(on attend) et de Move(On adresse un registre). Cette liste s'appelle copperliste (!). Regardez plutot ce petit exemple: Voici une petite copperliste: Attend ligne 50 et met $0000 dans $dff180 Attend ligne 51 et met $0111 dans $dff180 Attend ligne 52 et met $0222 dans $dff180 Attend ligne 53 et met $0333 dans $dff180 Attend ligne 54 et met $0444 dans $dff180 Attend ligne 55 et met $0555 dans $dff180 Attend ligne 56 et met $0666 dans $dff180 Attend ligne 57 et met $0777 dans $dff180 Attend ligne 58 et met $0888 dans $dff180 Attend ligne 59 et met $0999 dans $dff180 Attend ligne 60 et met $0AAA dans $dff180 Attend ligne 61 et met $0BBB dans $dff180 Attend ligne 62 et met $0CCC dans $dff180 Attend ligne 63 et met $0DDD dans $dff180 Attend ligne 64 et met $0EEE dans $dff180 Attend ligne 65 et met $0FFF dans $dff180 Que va exécuter le copper losqu'il va lire cette liste eblouissante ? Le registre $dff180 est le registre qui definie la couleur 0, c'est à dire la couleur de fond. Au niveau couleurs, $0000 correspond à du noir et $0FFF à du blanc. Les autres valeurs sont les étapes intermediaires entre le noir et le blanc. Si je suis la logique du copper, on commence par attendre la ligne 50 de l'écran. Le faisceau commence toujours en haut de l'écran ne l'oubliez jamais ! Une fois que le faisceau d'électrons y arrive, on met $0000 dans $DFF180, c'est à dire que le fond de l'écran va devenir noir à partir de cet endroit. Le copper continue, il attend la ligne 51, cad la suivante et là pareil il change aussi la couleur de fond en y mettant un noir un peu plus clair(?) enfin du gris trés foncé. Et jusqu'à la ligne 65, le copper changera la couleur de fond en l'augmentant d'intensité toute les lignes. Qu'obtient-on concrètement ? Un degradé entre la ligne 50 et 65. Et ceci avec un seul registre de couleur, on peut donc avec une seule couleur faire un degradé sur tout l'écran si on le desire. Le copper exécute ses operations en parallèele avec tout le reste. Ca devient de la folie au niveau multitâche. non ? :) II.2.5 Les Sprites Les sprites sont aussi apellés des "lutins". C'est rigolo mais on n'utilise jamais cette appellation. Ca me fait juste marrer(!!). Pourquoi "lutins" ? Il faut encore remonter au Commodore64 cette magnifique machine. A l'epoque déjà, les sprites existaient. Il y avait dans les jeux de petits personnages qui bougaient et qui étaient constitués de sprites. Ces personnages n'existaient pas physiquement mais étaient pourtant bien réels sur l'écran. L'exemple le plus parlant de "lutins" sur Amiga est le pointeur de la souris sous workbench. Le truc rouge là que vous bougez avec la souris, et ben il n'existe pas. Si vous regardez à l'endroit où se trouve la mémoire écran, vous verrez le workbench mais pas le pointeur. Voila pourquoi on appelait les sprites "lutins" ou même "fantomes". Pour redevenir serieux, les sprites sont encore pris en charge par des circuits hard. Décidement l'architecture de l'Amiga est géniale. On peut le dire de temps à autre, dommage que ca aille pas plus vite on les niquerait tous ces pc de m#!((è....Ok je me calme... :). Un sprite est donc independant de l'écran. Il y en a 8 dans l'Amiga. Ils peuvent avoir une largeur de 64 pixels en 4 couleurs. La hauteur des sprites n'est pas limitée. ---------------------------------------------------------------------- Voila donc un premier cours qui explique grossièrement les choses. Je préfère que tout soit plus détaillé et même exagérément détaillé plutôt que d'aller vite et de perdre la moitié des lecteurs. L'assembleur s'apprend avec le temps mais je pense qu'avec des explications simplifiées au maximum on peut accélérer le processus. Si vous avez bien compris ce qui a été dit ici c'est bien. Dans le cas contraire, ne vous inquietez pas, cela viendra avec des exemples plus concrets que nous verrons par la suite... Nous attaquerons dès le prochain cours la programmation assembleur. Je vous conseille de vous procurer un assembleur pour pouvoir réaliser et mieux comprendre les exemples traités. On apprend plus vite en modifiant les sources et en observant les conséquences. L'assembleur que j'utilise est Asm-One 1.25. Vous pouvez utiliser un autre du genre DevPack mais les indications que je donnerai seront pour l'utilisation d'Asm-One uniquement. De toute façon, si j'utilise ce soft c'est que je suis persuadé que pour ce genre de programmation c'est le plus pratique et le plus rapide d'utilisation. A bientôt pour la suite du cours ... Oriens/ Les Oo Shadock \/ ©