Puce Calculer l'offset de déplacement sur une instruction conditionnelle

 

Avec un assembleur, facile, le compilateur calcule automatiquement la valeur à mettre après l'instruction. A la main, c'est moins drôle :

Si le saut est une instruction à la suite du code (en avant), il faut ajouter le nombre d'octets qui sépare l'instruction conditionnelle à l'instruction à exécuter (ne pas compter les octets utilisés pour l'instruction conditionnelle et l'instruction où l'on veut aller).

Si le saut est une instruction qui se trouve avant la condition (saut en arrière), il faut compter tous les octets y compris de l'instruction où l'on veut arriver et ceux de l'instruction conditionnelle (PC: program counter - le pointeur d'instructions est en effet déjà positionné sur l'instruction suivante).

Il faut ensuite connaître le principe du complément à 2 : le nombre total doit être converti en binaire (c'est plus simple). Ensuite :

  • Les bits à 0 passe à 1
  • Les bits à 1 passe à 0

Au résultat de cette inversion, il faut ajouter 1.

C'est peut-être plus simple à comprendre avec un exemple ?

Le code suivant marche pour une Atari 800XL, mais le principe de calcul reste évidemment le même pour les autres machines :

But : afficher 10 étoiles, puis changer la couleur de fond.

Mais ce n'est pas ce qui nous intéresse. Dans ce bête petit exemple, il y a une instruction conditionnelle qui boucle en " arrière " (il s'agit du BNE BCL) et une autre qui boucle en avant (il s'agit de BEQ BCL1).

 

  PLA 104
  LDA #10 169 10
  TAX 170
BCL:    
  STA 40000,X 157 64 156
  DEX 202
  BNE BCL 208 250
  BEQ BCL1 240 02
  RTS ;Code idiot, 96
  NOP ; mais ce n'est qu'un exemple 234
BCL1:    
  LDA #100 169 100
  STA 710 141 198 02
  RTS 96
     
     

La boucle BCL affiche les étoiles.

La boucle BCL1 change la couleur du fond.

 

 

Comment calculer la valeur à mettre après le BNE ?

Pour commencer, il faut imager que lorsque le 6502 exécute la fonction BNE BCL, le pointeur est déjà sur l'instruction suivante (dans notre cas, la ligne BEQ BCL1). Pour revenir à la ligne STA 40000,X, il faut donc compter le nombre d'octets qu'il y a avant le BEQ (code 240) et après le TAX (code 170). Ce qui donne 6 octets.

Pour indiquer que vous veulez revenir en arrière, il faut préciser un nombre négatif.

Pour rappel : un nombre signé sur un 6502 varie entre [-128, 127].

Comme il n'y a pas de possibilité de mettre un signe -, vous utilisez donc le 7ième bit comme signe (si positionné à 1, le nombre est négatif).

Pour avoir l'équivalent des nombres signés, vous appliquez le complément à 2 sur le nombre négatif.

Rappel, le complément à deux  : Il suffit d'inverser tous les bits. Sur ce nouveau nombre, ajouter 1.

Revenons à l'exemple : vous voulez revenir en arrière de 6 octets (-6).

En binaire, 6 = 110 sur 8 bits 00000110

Complément à deux :

Vous inversez tous les bits :11111001

et ajoutez 1 à 11111001. Ce qui donne 11111010 ou 250 en décimal. (au passage, le 7ième bit est bien positionné !).

Comment calculer la valeur à mettre après le BEQ ?

Cas le plus simple en fait. Comme dit précédemment, le pointeur est déjà sur l'instruction suivante. Dans notre exemple, il s'agit du RTS (code 96). Nous voulons arriver à BCL1 (en fait, le LDA de code 169). Il suffit de compter les octets compris entre RTS (inclus) et LDA (exclus). Ce qui nous donne deux octets...c'est fini !

Le programme basic pour l'Atari 800XL : boucle.lst

 

Petit exercice: traduire le programme pour le C64...si vous n'avez rien d'autre à faire !

Sauf que le code 10 affiche un J et pas un *.

Il ne faut pas mettre le PLA pour rendre la main au BASIC

L'adresse écran est 1024 et celui de la couleur est 53281 (Ne pas oublier que les adresses sont indiquées avec d'abord la partie basse puis la partie haute 53281 donne $D021 donc: STA 53281 se traduit donc 8D 21 D0 ou encore en décimal 141 33 208).

Pour exécuter le programme il faut utiliser la commande SYS (adr) ou adr est l'adresse du code machine.