samedi 23 août 2014

Modes d'adressage [fr]

Étudions maintenant quelques modes d'adressage.

Qu'est-ce donc déjà ?

Nous avons vu que nous pouvions stocker des données en mémoire via des labels. Et bien, il est tout à fait possible ensuite pour le CPU de lire ou d'écrire dedans. Pour cela, nous allons utiliser un simple move qui va donc bouger un contenu mémoire dans par exemple un registre de notre choix.

Ce move sera accompagné d'un des nombreux mode d'adressage disponible par nos 68k, surtout sur les 68020+. A partir de ce CPU, les ingénieurs en ont en effet rajouté une tripotée.

Reprenons notre petit programme :

 
L'adresse de __MesDonnees est donc dans a2. Afin de bouger $CAFECAFE dans d1, il suffit d'utiliser le mode d'adressage le plus simple : (ax) ! Il y en a beaucoup d'autres que nous verrons au fur et à mesure.

Les parenthèses signifient "contenu" : ce mode d'adressage va donc bouger ce que contient l'adresse stockée dans a2.

Je récapitule pour que tout cela soit très clair :
  • move.l a2,d0 = bouge l'adresse dans le registre d0
  • move.l (a2), d0 = bouge le contenu de l'adresse dans le registre d0

Toujours en traçant le programme avec le débugger, vous pouvez voir que $CAFECAFE arrive bien dans notre registre de donnée d1.

Ensuite, il est tout à fait possible d'ajouter un décalage à (ax) : il suffit de rajouter devant le chiffre désiré. Ici pour notre exemple, nous allons bouger nos données en mémoire dans trois registres de données. Le 4(a2) va donc chercher __MesDonnees+4, c'est à dire $1111 puisque ce move est .w !

Noter que a2 n'est pas modifié par le CPU : il effectue juste une addition (+4 donc) pour lui et a2 reste intact. a2 = __MesDonnees est en quelque sorte une référence, et les chiffres additions devant servent juste à atteindre les données désirées.

Pour finir, le dernier move va bouger l'octet $FF dans d3...

A travers cet exemple, nous avons lu : il est aussi tout à fait possible d'écrire :

d1, d2 et d3 deviennent source et vont écrire dans les destinations (a2), 1(a2), 2(a2) et 4(a2).

Voici le résultat dans la mémoire :

Voilà, bonne progression aujourd'hui, vous comprenez de mieux en mieux le langage assembleur...

Avouez que c'est tout à fait accessible et surtout très logique !
  

samedi 16 août 2014

Les labels (III) [fr]

Voici un meilleur schéma de l'organisation mémoire de notre petit programme d'exemple.

J'ai repris avec la largeur du tube 32 bits qui est plus explicite je trouve...

Il est important de bien voir et comprendre aussi le "poids" de chaque mnémonique. En effet, notre premier move "pèse" 12 octets ce qui signifie que lorsque notre programme contenu en mémoire fast ou chip doit "entrer" dans le coeur du CPU pour y être exécuter, il faut y transférer nos 12 octets représentant le move, ce qui prends un certain temps.

Les accès mémoire sont lents sur la majorité de nos Amiga Classics, à part certains équipés de cartes accélératrice comme la MK3 bien overclockée par exemple...

Lorsque le CPU transfère du contenu mémoire, il attends que les données arrivent en son sein, donc vous comprenez que le poids des instructions doit être le plus léger possible : plus court = plus rapide à entrer dans le CPU = le CPU attends moins = le programme va donc plus vite. Et prends aussi moins de place dans le code cache, nous verrons cela plus tard...

Nous découvrirons bientôt qu'il existe une astuce pour avoir $00000000 dans a0 pesant seulement un mot alors qu'ici l'instruction utilisée prends en tout trois mots...

Comme je l'affirmais précédemment, autant prendre les bonnes habitudes dès le tout début : coder avec le poids des instructions en tête est très important, vous devez dès maintenant vous y habituer...
   

jeudi 7 août 2014

Les labels (II) [fr]

Bon, finalement continuons avec les labels et une nouvelle instruction : lea !

Cette nouvelle mnémonique permet de placer l'adresse d'un label dans un registre d'adresse. Bien souvent, ce label est une donnée ou une suite de données de votre choix. Parfois, cela peut-être également une routine...

Pour signifier des données, il suffit d'employer dc.b/.w/.l (qui n'est pas une instruction) comme le montre cette photo :

Donc ici, le premier lea va mettre l'adresse _MonPremierProggy dans a1 et le deuxième l'adresse __MesDonnees dans le registre a2.

a1 va être l'adresse qui contient le move.l $00000000,d0 alors que a2 est le début de nos données. Les dc servent à signifier à AsmPro qu'il doit mettre vos données choisies à cet endroit, c'est tout.

Toujours vérifier mes dire avec le monitor d'AsmPro :

AsmPro et le Kickstart ont remplacé les labels par des adresses de façon automatique comme expliqué dans le précédent article. La colonne tout à gauche indique les adresses fastram dans lesquelles se trouvent notre petit programme : c'est le tube mémoire dont je parlais plus tôt dans ces cours. Ensuite, la deuxième nous montre les données contenues dans chacune de ces adresses. Et la troisième l'interprétation de ces données.

Alors, nos move et lea sont des instructions faites de lettres et chiffres compréhensibles pour les humains. Elles sont encodées (ou interprétées) par uniquement des 0 et des 1 par le CPU qui ne comprends que ça le pauvre. Ici, elles sont en hexadécimal car par convention, les adresses s'écrivent toujours en hexa : une suite de 32 zéros et uns serait trop compliquée à retenir ou interprêté pour nos cerveaux, l'hexa nous est bien utile ici pour simplifier les choses !
  • 203C encode move.l dans d0 et 00000000 à la donnée immédiate mot long
  • 303C encode move.w dans d0 et 8012 à la donnée immédiate mot
  • 207C encode move.l dans a0 et 00000000 à la donnée immédiate mot long
  • 43F9 encode lea dans a1 et 0A01D2A4 (_MonPremierProggy) à l'adresse de départ
  • 45F9 encode lea dans a2 et 0A1D2C0 (__MesDonnees) à l'adresse de nos données
  • CAFECAFE aucun encodage puisque dc = donnée, pas une instruction encodée
  • 1111 aucun encodage
  • FF aucun encodage

Là encore l'encodage est automatique par AsmPro. Je vous explique le principe de fonctionnement, vous n'avez qu'à apprendre les mnémoniques.

Voilà, à vous de bien cogiter ce nouvel article maintenant !
  

samedi 2 août 2014

Les labels (I) [fr]

Continuons notre apprentissage dans la joie et la bonne humeur avec aujourd'hui les labels qui sont en fait des adresses.

Il y a plusieurs types de labels. Les premiers sont ceux indiquant le début d'une routine. Reprenons notre exemple de la dernière fois, et ajoutons au tout début un nom à nos trois instructions. Il est conseillé de les précéder d'un _ afin de bien les reconnaître :

 
Viennent ensuite les branchements. Pour vous les expliquez, je vous présente maintenant une nouvelle mnémonique : beq qui signifie Branch if EQual. Elle fonctionne tout simplement en analysant le CCR. Si le bit Z est à zéro, et bien le programme sautera au label indiqué (ici .branch_si_zero qu'il est coutume de précéder d'un .). Reprenons notre exemple et rajoutant quelques instructions simples :

  
Lorsque le programme s'exécute, il arrive à notre beq et regarde le CCR : son bit Z n'est pas à zéro puisque la précédente instruction agissait sur un registre d'adresse, c'est donc le move.w $8012,d0 qui a le dernier mis à jour le CCR.

Donc, notre beq ne va rien faire du tout et va aller à la prochaine instruction qui move.l #$00000001,d0.

Ensuite en continuant le programme, avec cette fois le move.l #$00000000,d0 le CCR aura bien son bit Z à zéro et notre deuxième beq ira donc directos cette fois au second label .branch_si_zero2, c'est à dire au move.w #$FFFF,d1 :

  
Encore une fois, amusez-vous à tester par vous même sous AsmOne pour mieux comprendre... Il suffit de tracer une à une les mnémoniques avec la flèche du bas.

Il existe d'autres labels, nous verrons plus tard...

Pour finir, vérifiez par vous-même que les labels sont des adresses. Allez dans les menus déroulants, sélectionner Assemble, et ensuite Monitor :

  
En effet, AmigaOS est multitâche et c'est le Kickstart qui s'occupe automatiquement de la gestion des adresses avec quelques exceptions comme par exemple celles de la mémoire écran (chipmem) qui peuvent être utilisées directement par les coders.

Lorsque vous assemblez (= convertir un fichier source avec les mnémoniques intelligibles pour nous les humains en langage machine fait de 0 et 1 compréhensibles par le CPU) notre petit programme, AmigaOS décidera lui-même de le placer à une adresse mémoire disponible, et qui sera certainement toujours différente d'une fois à l'autre. Rassurez-vous, nous y reviendrons...
  
Pour cette exemple, AmigaOS et AsmOne ont placé notre _MonPremierProggy à l'adresse fastram $0A7E04C. Ils ont ensuite remplacé nos deux branchements par des adresses.

Je simplifie volontairement pour rester compréhensible aux débutants, nous irons plus loin plus tard...