Chapitre 4 : Le didacticiel sur le langage d'assemblage du microprocesseur 6502

Chapitre 4 Le Didacticiel Sur Le Langage D Assemblage Du Microprocesseur 6502



Chapitre 4 : Le didacticiel sur le langage d'assemblage du microprocesseur 6502

4.1 Introduction

Le microprocesseur 6502 a été lancé en 1975. Il était alors utilisé comme microprocesseur pour certains ordinateurs personnels tels que Apple II, Commodore 64 et BBC Micro.







Le microprocesseur 6502 est encore produit en grande quantité aujourd'hui. Il ne s’agit plus d’une unité centrale de traitement utilisée aujourd’hui dans les ordinateurs personnels (ordinateurs portables), mais elle est toujours produite en grande quantité et utilisée aujourd’hui dans les appareils électroniques et électriques. Afin de comprendre les architectures informatiques les plus modernes, il est très utile d’examiner un microprocesseur plus ancien mais assez performant tel que le 6502.



Comme il est simple à comprendre et à programmer, c’est l’un des meilleurs (sinon le meilleur) microprocesseur à utiliser pour enseigner le langage assembleur. Le langage assembleur est un langage de bas niveau qui peut être utilisé pour programmer un ordinateur. Notez que le langage assembleur d’un microprocesseur est différent du langage assembleur d’un autre microprocesseur. Le langage assembleur du microprocesseur 6502 est enseigné dans ce chapitre. Plus précisément, c'est le 65C02 qui est enseigné, mais simplement désigné sous le nom de 6502.



Un ordinateur célèbre dans le passé s'appelle le commodore_64. Le 6502 est un microprocesseur de la famille 6500. L'ordinateur Commodore_64 utilise le microprocesseur 6510. Le microprocesseur 6510 est du 6500 µP. Le jeu d’instructions du 6502 µP contient presque toutes les instructions du 6510 µP. Les connaissances de ce chapitre et du suivant sont basées sur l'ordinateur commodore_64. Ces connaissances servent de base pour expliquer les architectures informatiques modernes et les systèmes d'exploitation modernes dans cette partie du cours de carrière en ligne.





L'architecture informatique fait référence aux composants de la carte mère de l'ordinateur et à une explication de la façon dont les données circulent au sein de chaque composant, en particulier le microprocesseur, comment les données circulent entre les composants et également comment les données interagissent. Le singulier pour data est datam. Un moyen efficace d’étudier l’architecture informatique d’un ordinateur consiste à étudier le langage assembleur de la carte mère.

L'ordinateur Commodore_64 est dit être un ordinateur de mot informatique de 8 bits. Cela signifie que les informations sont stockées, transférées et manipulées sous forme de codes binaires à huit bits.



Schéma fonctionnel de la carte mère Commodore 64
Le schéma fonctionnel de la carte mère Commodore 64 est le suivant :


Fig 4.1 Schéma fonctionnel de l'unité système Commodore_64

Imaginez le microprocesseur 6510 comme le microprocesseur 6502. La mémoire totale est une série d'octets (8 bits par octet). Il existe la mémoire à accès aléatoire (lecture/écriture) dans laquelle les octets peuvent être écrits ou effacés. Lorsque l'alimentation de l'ordinateur est coupée, toutes les informations de la mémoire vive (RAM) sont effacées. Il existe également la mémoire morte (ROM). Lorsque l'alimentation de l'ordinateur est coupée, les informations contenues dans la ROM restent (ne sont pas effacées).

Il y a le port (circuit) d’entrée/sortie qui est appelé dispositifs d’entrée/sortie dans le schéma. Ce port ne doit pas être confondu avec les ports visibles sur les surfaces verticales gauche et droite ou avant et arrière de l'unité système informatique. Ce sont deux choses différentes. Les connexions de ce port interne aux périphériques tels que le disque dur (ou la disquette), le clavier et le moniteur ne sont pas illustrées dans le schéma.

Il y a trois bus (groupes de très petits conducteurs électriques) dans le schéma. Chaque fil peut transférer un bit 1 ou un bit 0. Le bus de données, pour le transfert d'octets de huit bits à la fois (une impulsion d'horloge) vers la RAM et le port d'entrée/sortie (périphériques d'entrée/sortie), est bidirectionnel. Le bus de données a une largeur de huit bits.

Tous les composants sont connectés au bus d'adresse. Le bus d'adresses est unidirectionnel depuis le microprocesseur. Il y a seize conducteurs pour le bus d'adresses, et chacun transporte un bit (1 ou 0). Seize bits sont envoyés en une seule impulsion d'horloge.

Il y a le bus de contrôle. Certains conducteurs du bus de commande transféreraient chacun un bit du microprocesseur vers les autres composants. Quelques lignes de contrôle transportent les bits du port d'entrée/sortie (IO) vers le microprocesseur.

Mémoire d'ordinateur
La RAM et la ROM sont considérées comme un seul ensemble mémoire. Cet ensemble est représenté schématiquement comme suit où les nombres hexadécimaux portent le préfixe « $ » :


Fig 4.11 Disposition de la mémoire pour l'ordinateur Commodore 64

La RAM est de 0000 16 à DFFF 16 qui s'écrit de 0000 $ à $DFFF. Avec le langage assembleur 6 502 µP, un nombre hexadécimal est préfixé par « $ » et non suffixé (indice) par 16 ou H ou hex. Toutes les informations contenues dans la RAM disparaissent lorsque l'ordinateur est éteint. La ROM commence à partir de 000 $ E000 jusqu'à FFFF $. Il comporte des sous-programmes qui ne se déclenchent pas lorsque l'ordinateur est éteint. Ces sous-programmes sont les routines couramment utilisées qui aident à la programmation. Le programme utilisateur les appelle (voir chapitre suivant).

L'espace (octets) de $0200 à $D000 est réservé aux programmes utilisateur. L'espace entre $D000 et $DFFF est destiné aux informations directement liées aux périphériques (périphériques d'entrée/sortie). Cela fait partie du système d'exploitation. Ainsi, le système d'exploitation de l'ordinateur Commodore-64 est composé de deux parties principales : la partie en ROM qui ne s'éteint jamais et la partie de 000 $ à DFFF qui s'éteint lorsque l'alimentation est coupée. Ces données IO (entrée/sortie) doivent être chargées à partir d'un disque à chaque mise sous tension de l'ordinateur. Aujourd'hui, ces données sont appelées pilotes périphériques. Les périphériques commencent depuis le port du périphérique d'entrée/sortie en passant par les connexions de la carte mère jusqu'aux ports identifiables sur les surfaces verticales de l'ordinateur auxquels le moniteur, le clavier, etc. sont connectés et aux périphériques eux-mêmes (moniteur, clavier, etc. .).

La mémoire se compose de 2 16 = 65 536 emplacements d’octets. Sous forme hexadécimale, ce sont 10 000 16 = 10000 H = 10000 hexadécimal = 10 000 $ d'emplacements. En informatique, compter en base deux, base dix, base seize, etc. commence à partir de 0 et non de 1. Ainsi, le premier emplacement est en fait le numéro d'emplacement de 0000000000000000. 2 = 0 dix = 0000 16 = 0000 $. Dans le langage assembleur 6502 µP, l'identification d'un emplacement d'adresse est préfixée par $ et il n'y a pas de suffixe ni d'indice. Le dernier emplacement est le numéro d'emplacement 1111111111111111. 2 = 65 535 dix = FFFF 16 = $FFFF et non 10000000000000000 2 , soit 65 536 dix , soit 10 000 16 , ou 10 000 $. Les 10000000000000000 2 , 65 536 dix , 10000 16 , ou 10 000 $ donne le nombre total d'emplacements d'octets.

Ici, 2 16 = 65 536 = 64 x 1 024 = 64 x 2 dix = 64 Ko (Kilo-octets). Le suffixe 64 dans le nom Commodore-64 signifie 64 Ko de mémoire totale (RAM et ROM). Un octet est composé de 8 bits, et les 8 bits seront placés dans un emplacement d'octet dans la mémoire.

Les 64 Ko de mémoire sont divisés en pages. Chaque page contient 0100 16 = 256 dix emplacements des octets. Les 256 premiers dix = premier 0100 16 emplacements est la page 0. La deuxième est la page 1, la troisième est la page 2, et ainsi de suite.

Afin d'adresser les 65 536 emplacements, 16 bits sont nécessaires pour chaque emplacement (adresse). Ainsi, le bus d'adresses du microprocesseur vers la mémoire est constitué de 16 lignes ; une ligne pour un bit. Un bit vaut 1 ou 0.

Les registres 6502 µP
Un registre est comme les cellules d'octets d'un emplacement de mémoire d'octets. Le 6502 µP dispose de six registres : cinq registres de 8 bits et un registre de 16 bits. Le registre de 16 bits est appelé Program Counter, abrégé en PC. Il contient l'adresse mémoire pour l'instruction suivante. Un programme en langage assembleur se compose d’instructions placées en mémoire. Seize (16) bits différents sont nécessaires pour adresser un emplacement d'octet particulier dans la mémoire. A une impulsion d'horloge particulière, ces bits sont envoyés aux lignes d'adresse de 16 bits du bus d'adresse pour la lecture d'une instruction. Tous les registres pour le 6502 µP sont représentés comme suit :


Fig. 4.12 Registres 6 502 µP

Le compteur de programme ou le PC peut être vu comme un registre de 16 bits dans le diagramme. Les huit bits de poids faible sont appelés PCL pour Program Counter Low. Les huit bits de poids le plus élevé sont appelés PCH pour Program Counter High. Une instruction en mémoire pour le Commodore-64 peut comprendre un, deux ou trois octets. Les 16 bits du PC pointent vers la prochaine instruction à exécuter, en mémoire. Parmi les circuits du microprocesseur, deux d’entre eux sont appelés Unité Logique Arithmétique et Décodeur d’Instructions. Si l'instruction actuelle traitée dans le µP (microprocesseur) est longue d'un octet, ces deux circuits augmentent le PC pour l'instruction suivante d'1 unité. Si l'instruction actuelle en cours de traitement dans le µP est longue de deux octets, ce qui signifie qu'elle occupe deux octets consécutifs en mémoire, ces deux circuits augmentent le PC pour l'instruction suivante de 2 unités. Si l'instruction actuelle en cours de traitement dans le µP est longue de trois octets, ce qui signifie qu'elle occupe trois octets consécutifs en mémoire, ces deux circuits augmentent le PC pour l'instruction suivante de 3 unités.

L'accumulateur « A » est un registre à usage général de huit bits qui stocke le résultat de la plupart des opérations arithmétiques et logiques.

Les registres « X » et « Y » sont chacun utilisés pour compter les étapes du programme. Le comptage en programmation commence à partir de 0. Ils sont donc appelés registres d'index. Ils ont quelques autres objectifs.

Bien que le registre Stack Pointer, « S » comporte 9 bits, ce qui est considéré comme un registre de huit bits. Son contenu pointe vers un emplacement d'octet dans la page 1 de la mémoire vive (RAM). La page 1 commence à partir de l'octet $0100 (256 dix ) en octet $01FF (511 dix ). Lorsqu'un programme est en cours d'exécution, il passe d'une instruction à l'autre consécutive dans la mémoire. Cependant, ce n'est pas toujours le cas. Il arrive parfois qu'il saute d'une zone mémoire à une autre zone mémoire pour continuer à y exécuter les instructions, consécutivement. La page 1 de la RAM est utilisée comme pile. La pile est une grande zone de mémoire RAM qui contient les adresses suivantes pour la suite du code à partir de laquelle il y a un saut. Les codes avec instructions de saut ne sont pas dans la pile ; ils sont ailleurs dans la mémoire. Cependant, une fois les instructions de saut exécutées, les adresses de continuation (et non les segments de code) se trouvent dans la pile. Ils y ont été poussés suite aux instructions de saut ou de branchement.

Le registre d'état du processeur à huit bits de P est un type spécial de registre. Les bits individuels ne sont ni liés ni connectés les uns aux autres. Chaque bit s'appelle un drapeau et est apprécié indépendamment des autres. Les significations des drapeaux sont données ci-après selon les besoins.

Le premier et le dernier index binaire de chaque registre sont indiqués au-dessus de chaque registre dans le diagramme précédent. Le comptage de l'index (position) des bits dans un registre commence à 0 à droite.

Pages mémoire en binaire, hexadécimal et décimal
Le tableau suivant montre le début des pages mémoire en binaire, hexadécimal et décimal :

Chaque page contient 1 000 0000 2 nombre d'octets égal à 100 H nombre d'octets égal à 256 dix nombre d'octets. Dans le schéma mémoire précédent, les pages sont indiquées en montant à partir de la page 0 et non en descendant comme indiqué dans le tableau.

Les colonnes binaires, hexadécimales et décimales de ce tableau donnent les adresses d'emplacement des octets mémoire dans leurs différentes bases. Notez que pour la page zéro, seuls les bits de l'octet de poids faible sont nécessaires à la saisie lors du codage. Les bits de l'octet supérieur peuvent être omis puisqu'ils sont toujours des zéros (pour la page zéro). Pour le reste des pages, les bits de l'octet de poids fort doivent être utilisés.

Le reste de ce chapitre explique le langage assembleur 6502 µP en utilisant toutes les informations précédentes. Afin de comprendre rapidement la langue, le lecteur doit additionner et soustraire en base seize au lieu de base dix. Il est en fait censé être en base deux, mais le calcul en base deux est fastidieux. N'oubliez pas que lorsque vous additionnez deux nombres en base deux, un report vaut toujours 1 comme en base dix. Mais lorsqu’on soustrait deux nombres en base deux, un emprunt vaut deux et non dix comme en base dix. Lors de l'addition de deux nombres en base seize, un report vaut toujours 1 comme en base dix. Mais lorsqu’on soustrait deux nombres en base seize, un emprunt vaut seize et non dix comme en base dix.

4.2 Instructions de transfert de données

Considérez le tableau suivant des instructions de transfert de données en langage assembleur pour le 6502 µP :

Lorsqu'un octet (8 bits) est copié d'un emplacement d'octet de mémoire vers le registre d'accumulateur, le registre X ou le registre Y, le chargement est en cours. Lorsqu'un octet est copié de l'un de ces registres vers un emplacement d'octet de mémoire, il s'agit d'un transfert. Lorsqu'un octet est copié d'un registre à un autre, le transfert continue. Dans la deuxième colonne du tableau, la flèche indique le sens de la copie pour un octet. Le reste des quatre colonnes affiche différents modes d'adressage.

Une entrée dans la colonne du mode d'adressage est le code d'octet réel de la partie mnémonique correspondante de l'instruction en hexadécimal. AE, par exemple, est le code d'octet réel pour LDX qui consiste à charger un octet de la mémoire dans le registre X en mode d'adressage absolu comme AE. 16 = 10101110 2 . Ainsi, les bits pour LDX dans un emplacement d’octet de mémoire sont 10101110.

Notez que pour la partie mnémonique LDX de l'instruction, il existe trois octets possibles qui sont A2, AE et A6, et chacun est destiné à un mode d'adressage particulier. Lorsque l'octet qui se charge dans le registre X ne doit pas être copié depuis un emplacement d'octet mémoire, la valeur doit être saisie avec (juste après) le mnémonique LDX dans l'instruction en hexadécimal ou décimal. Dans ce chapitre, ces valeurs sont saisies en hexadécimal. Il s'agit d'un adressage immédiat, donc l'octet réel en mémoire pour représenter LDX est A2 16 = 10100010 2 et pas AE 16 qui est égal à 10101110 2 .

Dans le tableau, tous les octets sous les en-têtes du mode d'adressage sont appelés codes d'opération, abrégés en codes d'opération. Il peut y avoir plus d'un opcode pour un mnémonique, selon le mode d'adressage.

Note: Le mot « charger » dans l'unité du système informatique peut avoir deux significations : il peut faire référence au chargement d'un fichier depuis un disque vers la mémoire de l'ordinateur ou il peut faire référence au transfert d'un octet d'un emplacement d'octet de mémoire vers un registre du microprocesseur. .

Il existe plus de modes d'adressage que les quatre indiqués dans le tableau pour le 6 502 µP.

Sauf indication contraire, tous les codes de programmation utilisateur de ce chapitre commencent à l'adresse 0200. 16 qui est le début de la zone utilisateur dans la mémoire.

Mémoire M et accumulateur A

Mémoire vers accumulateur

Adressage immédiat
L'instruction suivante stocke le nombre FF 16 = 255 dix dans l'accumulateur :

MDL #$FF

Le « $ » n'est pas seulement utilisé pour identifier une adresse mémoire. En général, il est utilisé pour indiquer que le prochain nombre qui suit est hexadécimal. Dans ce cas, $FF n'est l'adresse d'aucun emplacement d'octet de mémoire. C'est le nombre 255 dix en hexadécimal. La base 16 ou l’un de ses autres indices équivalents ne doit pas être écrit dans l’instruction du langage assembleur. Le « # » indique que ce qui suit ensuite est la valeur à mettre dans le registre accumulateur. La valeur peut également être écrite en base dix, mais cela n'est pas fait dans ce chapitre. Le « # » signifie un adressage immédiat.

Un mnémonique a une certaine ressemblance avec la phrase anglaise correspondante. « LDA #$FF » signifie charger le numéro 255 dix dans l'accumulateur A. Puisqu'il s'agit d'un adressage immédiat du tableau précédent, LDA est A9 et non AD ou A5. A9 en binaire est 101010001. Ainsi, si A9 pour LDA est dans l'adresse $0200 dans la mémoire, $FF est dans l'adresse $0301 = 0300 + 1. Le #$FF est précisément l’opérande du mnémonique LDA.

Adressage absolu
Si la valeur de $FF se trouve à l'emplacement $0333 de la mémoire, l'instruction précédente est :

LDA 0333 $

Notez l'absence de #. Dans ce cas, l'absence de # signifie que ce qui suit est une adresse mémoire et non la valeur qui nous intéresse (pas la valeur à mettre dans l'accumulateur). Ainsi, l'opcode pour LDA, cette fois, est AD et non A9 ou A5. L'opérande de LDA ici est l'adresse $0333 et non la valeur $FF. $FF se trouve à l'emplacement 0333 $, qui est plutôt éloigné. L'instruction « LDA $0333 » occupe trois emplacements consécutifs dans la mémoire, et non deux, comme le faisait l'illustration précédente. « AD » pour LDA se trouve à l'emplacement 0200 $. L'octet inférieur de 0333, soit 33, se trouve à l'emplacement $0301. L'octet supérieur de $0333, soit 03, se trouve à l'emplacement $0302. Il s'agit du petit endianisme utilisé par le langage assembleur 6502. Les langages d'assemblage des différents microprocesseurs sont différents.

Ceci est un exemple d’adressage absolu. Le $0333 est l'adresse de l'emplacement qui a $FF. L'instruction se compose de trois octets consécutifs et n'inclut pas le $FF ni son emplacement réel d'octet.

Adressage de page zéro

Supposons que la valeur $FF se trouve dans l’emplacement mémoire $0050 de la page zéro. Les emplacements d'octets pour la page zéro commencent à 0000 $ et se terminent à 00FF $. Ce sont 256 dix emplacements au total. Chaque page de la mémoire du Commodore-64 contient 256 dix long. Notez que l'octet le plus élevé est zéro pour tous les emplacements possibles dans l'espace de page zéro en mémoire. Le mode d'adressage page zéro est le même que le mode d'adressage absolu, mais l'octet de poids fort 00 n'est pas saisi dans l'instruction. Ainsi, pour charger le $FF de l'emplacement $0050 dans l'accumulateur, l'instruction du mode d'adressage de page zéro est :

MDL 50 $

Avec LDA étant A5 et non A9 ou AD, A5 16 = 10100101 2 . N'oubliez pas que chaque octet de la mémoire est composé de 8 cellules et que chaque cellule en contient un peu. L'instruction ici se compose de deux octets consécutifs. A5 pour LDA se trouve à l’emplacement mémoire $0200 et l’adresse $50, sans l’octet supérieur de 00, se trouve à l’emplacement $0301. L'absence de 00, qui aurait consommé un octet dans la mémoire totale de 64 Ko, permet d'économiser l'espace mémoire.

Accumulateur en mémoire

Adressage absolu
L'instruction suivante copie une valeur d'octet, quelle qu'elle soit, de l'accumulateur vers l'emplacement mémoire de $1444 :

ILS valent 1444 $

On dit qu'il s'agit d'un transfert de l'accumulateur vers la mémoire. Il ne se charge pas. Le chargement est le contraire. L'octet de code d'opération pour STA est 8D 16 = 10001101 2 . Cette instruction est constituée de trois octets consécutifs dans la mémoire. Le 8D 16 est à l'emplacement 0200 $. Le 44 16 de l'adresse $1444 se trouve à l'emplacement $0201. Et 14 16 est à l'emplacement $0202 – petit boutisme. L'octet réel copié ne fait pas partie de l'instruction. 8D et non 85 pour l'adressage de page zéro (dans le tableau) sont utilisés ici pour STA.

Adressage de page zéro
L'instruction suivante copie une valeur d'octet, quelle qu'elle soit, de l'accumulateur vers l'emplacement mémoire $0050 de la page zéro :

STA 0050 $

L'octet d'opcode pour STA est ici 85 16 = 10000101 2 . Cette instruction est constituée de deux octets consécutifs en mémoire. Le 85 16 est à l'emplacement 0200 $. Les 50 16 de l'adresse 0050 $ se trouve à l'emplacement 0201 $. La question du boutisme ne se pose pas ici car l'adresse n'a qu'un seul octet qui est l'octet de poids faible. L'octet réel copié ne fait pas partie de l'instruction. 85 et non 8D pour l'adressage de page zéro sont utilisés ici pour STA.

Cela n'a pas de sens d'utiliser l'adressage immédiat pour transférer un octet de l'accumulateur vers un emplacement de la mémoire. En effet, la valeur réelle telle que $FF doit être citée dans l'instruction en adressage immédiat. Ainsi, un adressage immédiat n'est pas possible pour le transfert d'une valeur d'octet d'un registre du µP vers n'importe quel emplacement mémoire.

Mnémoniques LDX, STX, LDY et STY
LDX et STX sont respectivement similaires à LDA et STA. Mais ici, c'est le registre X qui est utilisé et non le registre A (accumulateur). LDY et STY sont respectivement similaires à LDA et STA. Mais ici, c'est le registre Y qui est utilisé et non le registre A. Reportez-vous au Tableau 4.21 pour chaque opcode en hexadécimal qui correspond à un mnémonique particulier et à un mode d'adressage particulier.

Transferts d'inscription à inscription
Les deux ensembles d'instructions précédents du tableau 4.21 traitent de la copie (transfert) de registres mémoire/microprocesseur et de la copie de registres/registres (transfert). Les instructions TAX, TXA, TAY, TYA, TSX et TXS effectuent la copie (transfert) du registre du microprocesseur vers un autre registre du même microprocesseur.

Pour copier l'octet de A vers X, l'instruction est :

IMPÔT

Pour copier l'octet de X vers A, l'instruction est :

Émission

Pour copier l'octet de A vers Y, l'instruction est :

MAIN

Pour copier l'octet de Y vers A, l'instruction est :

TYA

Pour l'ordinateur Commodore 64, la pile est la page 1 juste après la page 0 dans la mémoire. Comme toute autre page, elle comprend 25610 dix emplacements d'octets, de 0100 $ à 01FF $. Normalement, un programme s'exécute d'une instruction à l'instruction consécutive suivante dans la mémoire. De temps en temps, il y a un saut vers un autre segment de code mémoire (ensemble d'instructions). La zone de pile en mémoire (RAM) contient les adresses d'instruction suivantes à partir desquelles les sauts (ou branches) se sont arrêtés pour la suite du programme.

Le pointeur de pile « S » est un registre de 9 bits dans le 6502 µP. Le premier bit (le plus à gauche) est toujours 1. Toutes les adresses d'emplacement d'octet de la première page commencent par 1 suivi de 8 bits différents pour les 256 dix Emplacements. Le pointeur de pile a l'adresse de l'emplacement dans la page 1 qui contient l'adresse de la prochaine instruction que le programme doit renvoyer et continuer après l'exécution du segment de code actuel (accédé). Puisque le premier bit de toutes les adresses de la pile (première page) commence par 1, le registre du pointeur de pile n'a besoin de contenir que les huit bits restants. Après tout, son premier bit, qui est le bit le plus à gauche (le neuvième bit en partant de sa droite), est toujours 1.

Pour copier l'octet de S vers X, l'instruction est :

Bourse de Toronto

Pour copier l'octet de X vers S, l'instruction est :

SMS

Les instructions de registre à registre ne prennent aucun opérande. Ils se composent uniquement de mnémoniques. Chaque mnémonique a son opcode en hexadécimal. C'est en mode d'adressage implicite car il n'y a pas d'opérande (pas d'adresse mémoire, pas de valeur).

Note: Il n’y a pas de transfert X vers Y ou Y vers X (copie).

4.3 Opérations arithmétiques

Le circuit, Arithmetic Logic Unit dans le 6502 µP, ne peut ajouter que deux nombres de huit bits à la fois. Il ne soustrait pas, ne multiplie pas et ne divise pas. Le tableau suivant montre les opcodes et les modes d'adressage pour les opérations arithmétiques :

Note: Tous les mnémoniques pour les opérations arithmétiques et autres types d'opérations (c'est-à-dire tous les 6502 mnémoniques) prennent un octet de code d'opération (op). S'il existe plus d'un mode d'adressage pour le mnémonique, il y aura différents opcodes pour le même mnémonique : un par mode d'adressage. Les C, D et V dans le tableau sont les drapeaux du registre d'état. Leurs significations seront données ultérieurement selon les besoins.

Ajout de numéros non signés
Avec le 6502 µP, les nombres signés sont des nombres complémentaires à deux. Les nombres non signés sont des nombres positifs ordinaires commençant à zéro. Ainsi, pour un octet de huit bits, le plus petit nombre non signé est 00000000. 2 = 0 dix = 00 16 et le plus grand nombre non signé est 11111111 2 = 255 dix = FF 16 . Pour deux nombres non signés, l'addition est :

A+M+C→A

Cela signifie que le contenu de 8 bits de l'accumulateur est ajouté par l'unité logique arithmétique à un octet (8 bits) de la mémoire. Après l'ajout de A et M, la retenue jusqu'au neuvième bit est envoyée à la cellule d'indicateur de retenue dans le registre d'état. Tout bit de report précédent d'un ajout précédent qui se trouve toujours dans la cellule d'indicateur de report du registre d'état est également ajouté à la somme de A et M, faisant A+M+C→A. Le résultat est remis dans l’accumulateur.

Si l’ajout des intérêts est :

A+M

Et il n'est pas nécessaire d'ajouter un report précédent, l'indicateur de report doit être effacé et mis à 0, de sorte que l'ajout soit :

A+M+0→A identique à A+M→A

Note: Si M est ajouté à A et qu'un report de 1 se produit car le résultat est supérieur à 255 dix = 11111111 2 = FF 16 , c'est un nouveau report. Cette nouvelle retenue de 1 est automatiquement envoyée à la cellule d'indicateur de retenue au cas où la prochaine paire de huit bits aurait besoin d'être additionnée (un autre A + M).

Code pour ajouter deux huit bits non signés
00111111 2 +00010101 2 est le même que 3F 16 + 15 16 ce qui équivaut à 63 dix +21 dix . Le résultat est 010101002 2 ce qui équivaut à 54 16 et 84 dix . Le résultat ne dépasse pas le nombre maximum de huit bits qui est de 255 dix = 11111111 2 = FF 16 . Donc, il n’y a pas de retenue résultante de 1. Pour le dire autrement, la retenue résultante est 0. Avant l’addition, il n’y a pas de retenue précédente de 1. En d’autres termes, la retenue précédente est 0. Le code pour faire cet ajout peut être:

CTC
LDA #$3F
CDA #$15

Note: Lors de la saisie du langage assembleur, la touche « Entrée » du clavier est enfoncée à la fin de chaque instruction. Il y a trois instructions dans ce code. La première instruction (CLC) efface l'indicateur de retenue au cas où un ajout précédent aurait 1. CLC ne peut être effectué qu'en mode d'adressage implicite. Le mnémonique du mode d’adressage implicite ne prend aucun opérande. Cela efface la cellule de report du registre d'état de P. Effacer signifie donner le bit 0 à la cellule d'indicateur de report. Les deux instructions suivantes du code utilisent le mode d'adressage immédiat. Avec l'adressage immédiat, il n'y a qu'un seul opérande pour le mnémonique qui est un nombre (et ni une adresse mémoire ni un registre). Et donc, le numéro doit être précédé de « # ». Le « $ » signifie que le nombre qui suit est hexadécimal.

La deuxième instruction charge le nombre 3F 16 dans l'accumulateur. Pour la troisième instruction, le circuit de l'unité arithmétique et logique du µP prend le report précédent (effacé) de 0 (forcé à 0) de la cellule drapeau de report, du registre d'état et l'ajoute à 15 16 ainsi qu'à la valeur qui est déjà dans le 3F 16 accumulateur et remet le résultat complet dans l’accumulateur. Dans ce cas, il en résulte une retenue de 0. L'ALU (Arithmetic Logic Unit) envoie (met) 0 dans la cellule d'indicateur de retenue du registre d'état. Le registre d'état du processeur et le registre d'état signifient la même chose. S'il en résulte un report de 1, l'ALU envoie 1 au drapeau de report du registre d'état.

Les trois lignes de code précédentes doivent être en mémoire avant d'être exécutées. L'opcode 1816 pour CLC (adressage implicite) se trouve à l'emplacement d'octet 0200 $. L'opcode A9 16 pour LDA (adressage immédiat) se trouve à l'emplacement d'octet 0201 $. Le chiffre 3F dix se trouve à l'emplacement $0202 octet. L'opcode 69 16 pour LDA (adressage immédiat) se trouve à l'emplacement d'octet 0203 $. Le chiffre 15 dix se trouve à l'emplacement $0204 octet.

Note: LDA est une instruction de transfert (chargement) et non une instruction arithmétique (mnémonique).

Code pour ajouter deux seize bits non signés
Tous les registres du 6502 µP sont essentiellement des registres à huit bits, à l'exception du PC (Program Counter) qui est à 16 bits. Même le registre d'état a une largeur de 8 bits, bien que ses huit bits ne fonctionnent pas ensemble. Dans cette section, l'ajout de deux 16 bits non signés, avec une retenue de la première paire de huit bits à la deuxième paire de huit bits, est considéré. Le report qui nous intéresse ici est le report de la huitième position de bit à la neuvième position de bit.

Soit les nombres 0010101010111111 2 = 2ABF16 16 = 10 943 dix et 0010101010010101 2 = 2A95 16 = 10 901 dix . La somme est 0101010101010100 2 = 5554 16 = 21 844 dix .

L’addition de ces deux nombres non signés en base deux est la suivante :

Le tableau suivant montre le même ajout avec le report de 1 de la huitième position à la neuvième position, en commençant par la droite :

Lors du codage, les deux octets inférieurs sont ajoutés en premier. Ensuite, l'ALU (Arithmetic Logic Unit) envoie le report de 1 de la huitième position de bit à la neuvième position de bit, à la cellule d'indicateur de report dans le registre d'état. Le résultat de 0 1 0 1 0 1 0 0 sans report va à l'accumulateur. Ensuite, la deuxième paire d'octets est ajoutée avec le report. Le mnémonique ADC signifie ajouter automatiquement avec le report précédent. Dans ce cas, le report précédent, qui vaut 1, ne doit pas être modifié avant la deuxième addition. Pour le premier ajout, puisque tout report précédent ne fait pas partie de cet ajout complet, il doit être effacé (fait 0).

Pour l’addition complète des deux paires d’octets, la première addition est :

A + M + 0 -> A

Le deuxième ajout est :

A + M + 1 -> A

Ainsi, l'indicateur de report doit être effacé (valeur 0) juste avant le premier ajout. Le programme suivant dont le lecteur doit lire l'explication qui suit utilise le mode d'adressage absolu pour cette sommation :

CTC
LDA 0213 $
CAD 0215 $
; pas d'effacement car la valeur de l'indicateur de report est nécessaire
STA 0217 $
LDA 0214 $
CAD 0216 $
STA 0218 $

Notez qu'avec le langage assembleur 6502, un point-virgule commence un commentaire. Cela signifie que lors de l'exécution du programme, le point-virgule et tout ce qui se trouve à sa droite sont ignorés. Le programme préalablement écrit se trouve dans un fichier texte et est enregistré sous le nom choisi par le programmeur et avec l'extension « .asm ». Le programme précédent n’est pas exactement le programme qui va en mémoire pour être exécuté. Le programme correspondant dans la mémoire est appelé programme traduit où les mnémoniques sont remplacés par les opcodes (octets). Tout commentaire reste dans le fichier texte en langage assembleur et est supprimé avant que le programme traduit n'atteigne la mémoire. En fait, deux fichiers sont aujourd'hui enregistrés sur le disque : le fichier « .asm » et le fichier « .exe ». Le fichier « .asm » est celui de l’illustration précédente. Le fichier « .exe » est le fichier « .asm » avec tous les commentaires supprimés et tous les mnémoniques remplacés par leurs opcodes. Lorsqu'il est ouvert dans un éditeur de texte, le fichier « .exe » est méconnaissable. Sauf indication contraire, pour les besoins de ce chapitre, le fichier « .exe » est copié dans la mémoire à partir de l'emplacement $0200. C'est l'autre sens du chargement.

Les deux nombres de 16 bits à ajouter occupent quatre octets dans la mémoire pour l'adressage absolu : deux octets par nombre (la mémoire est une séquence d'octets). Avec l'adressage absolu, l'opérande de l'opcode est dans la mémoire. Le résultat de la sommation a une largeur de deux octets et doit également être placé dans la mémoire. Cela donne un total de 6 dix = 6 16 octets pour les entrées et les sorties. Les entrées ne proviennent pas du clavier et la sortie ne provient pas du moniteur ou de l'imprimante. Les entrées sont dans la mémoire (RAM) et la sortie (résultat de la sommation) retourne dans la mémoire (RAM) dans cette situation.

Avant qu'un programme soit exécuté, la version traduite doit d'abord être dans la mémoire. En regardant le code du programme précédent, on peut voir que les instructions sans commentaire constituent 19 dix = 13 16 octets. Ainsi, le programme passe de 0200 $ d'emplacement d'octet dans la mémoire à 0200 $ + 13 $ – 1 $ = 0212 $ d'emplacements d'octets (en commençant à partir de 0200 $ et non de 0201 $, ce qui implique – 1 $). L'ajout des 6 octets pour les numéros d'entrée et de sortie fait que tout le programme se termine à 0212 $ + 6 $ = 0218 $. La durée totale du programme est de 19 16 = 25 dix .

L'octet inférieur de l'augend doit être dans l'adresse $0213, et l'octet supérieur du même augend doit être dans l'adresse $0214 – petit endianisme. De même, l'octet inférieur de l'addend doit être dans l'adresse $0215, et l'octet supérieur du même addend doit être dans l'adresse $0216 – petit endianisme. L'octet inférieur du résultat (somme) doit être dans l'adresse $0217, et l'octet supérieur du même résultat doit être dans l'adresse $0218 – petit boutisme.

L'opcode 18 16 pour CLC (adressage implicite) se trouve à l’emplacement d’octet de 0200 $. L'opcode pour 'LDA $0213', c'est-à-dire AD 16 pour LDA (adressage absolu), se trouve à l’emplacement d’octet $0201. L'octet inférieur de l'augend, qui est 10111111, se trouve à l'emplacement d'octet mémoire $0213. N'oubliez pas que chaque opcode occupe un octet. L'adresse « $0213 » de « LDA $0213 » se trouve dans les emplacements d'octets de $0202 et $0203. L'instruction « LDA $0213 » charge l'octet inférieur de l'augend dans l'accumulateur.

L'opcode pour 'ADC $0215', c'est-à-dire 6D 16 pour ADC (adressage absolu), se trouve à l’emplacement d’octet $0204. L'octet inférieur de l'addend, qui est 10010101, se trouve à l'emplacement d'octet $0215. L'adresse « $0215 » de « ADC $0215 » se trouve dans les emplacements d'octets de $0205 et $0206. L'instruction « ADC $0215 » ajoute l'octet inférieur de l'addend à l'octet inférieur de l'augend qui est déjà dans l'accumulateur. Le résultat est remis dans l'accumulateur. Toute retenue après le huitième bit est envoyée à l'indicateur de retenue du registre d'état. La cellule du drapeau de retenue ne doit pas être effacée avant le deuxième ajout des octets supérieurs. Ce report est ajouté automatiquement à la somme des octets supérieurs. En fait, un report de 0 est ajouté automatiquement à la somme des octets inférieurs au début (ce qui équivaut à aucun report ajouté) à cause du CLC.

Le commentaire prend le prochain 48 dix = 30 16 octets. Cependant, cela ne reste que dans le fichier texte « .asm ». Il n'atteint pas la mémoire. Il est supprimé par la traduction effectuée par l'assembleur (un programme).

Pour l'instruction suivante qui est « STA $0217 », l'opcode de STA qui est 8D 16 (adressage absolu) se trouve à l’emplacement d’octet $0207. L'adresse « $0217 » de « STA $0217 » se trouve dans les emplacements mémoire de $0208 et $0209. L'instruction « STA $0217 » copie le contenu de huit bits de l'accumulateur vers l'emplacement mémoire de $0217.

L'octet supérieur de l'ajout, qui est 00101010, se trouve à l'emplacement mémoire de 0214 $, et l'octet supérieur de l'ajout, qui est 00101010, se trouve à l'emplacement d'octet de 02 $. 16 . L'opcode pour « LDA $0214 » qui est AD16 pour LDA (adressage absolu) se trouve à l'emplacement d'octet de $020A. L'adresse « $0214 » de « LDA $0214 » se trouve aux emplacements de $020B et $020C. L'instruction « LDA $0214 » charge l'octet supérieur de l'augend dans l'accumulateur, effaçant tout ce qui se trouve dans l'accumulateur.

L'opcode pour 'ADC $0216' qui est 6D 16 pour ADC (adressage absolu) se trouve à l’emplacement d’octet $020D. L'adresse « $0216 » de « ADC 0216 » se trouve dans les emplacements d'octets de $020E et $020F. L'instruction « ADC $0216 » ajoute l'octet supérieur de l'addend à l'octet supérieur de l'augend qui est déjà dans l'accumulateur. Le résultat est remis dans l’accumulateur. S'il y a un report de 1, pour ce deuxième ajout, il est automatiquement placé dans la cellule de report du registre d'état. Bien que le report au-delà du seizième bit (à gauche) ne soit pas requis pour ce problème, il est bon de vérifier si un report de 1 s'est produit en vérifiant si l'indicateur de report est devenu 1.

Pour la prochaine et dernière instruction qui est « STA $0218 », l'opcode de STA qui est 8D16 (adressage absolu) se trouve à l'emplacement d'octet de $0210. L'adresse « $0218 » de « STA $0218 » se trouve dans les emplacements mémoire de $0211 et $0212. L'instruction « STA $0218 » copie le contenu de huit bits de l'accumulateur vers l'emplacement mémoire de $0218. Le résultat de l’addition des deux nombres de seize bits est 0101010101010100, avec l’octet inférieur de 01010100 dans l’emplacement mémoire de 0217 $ et l’octet supérieur de 01010101 dans l’emplacement mémoire de 0218 $ – petit boutisme.

Soustraction
Avec le 6502 µP, les nombres signés sont des nombres complémentaires à deux. Un nombre complémentaire à deux peut être composé de huit bits, de seize bits ou de tout multiple de huit bits. Avec le complément à deux, le premier bit en partant de la gauche est le bit de signe. Pour un nombre positif, ce premier bit vaut 0 pour indiquer le signe. Le reste des bits forme le nombre de la manière normale. Pour obtenir le complément à deux d’un nombre négatif, inversez tous les bits du nombre positif correspondant, puis ajoutez 1 au résultat à l’extrémité droite.

Pour soustraire un nombre positif d’un autre nombre positif, la soustraction est convertie en un nombre négatif complémentaire à deux. Ensuite, la fin du menu et le nouveau nombre négatif sont ajoutés de la manière normale. Ainsi, la soustraction de huit bits devient :

Où le report est supposé égal à 1. Le résultat dans l’accumulateur est la différence du complément à deux. Ainsi, pour soustraire deux nombres, le drapeau de report doit être défini (mis à 1).

Lors de la soustraction de deux nombres de seize bits, la soustraction est effectuée deux fois comme pour l'ajout de deux nombres de seize bits. Puisque la soustraction est une forme d'addition avec le 6502 µP, lors de la soustraction de deux nombres de seize bits, l'indicateur de retenue n'est défini qu'une seule fois pour la première soustraction. Pour la deuxième soustraction, tout réglage du drapeau de retenue se fait automatiquement.

La programmation de la soustraction pour les nombres à huit bits ou à seize bits se fait de la même manière que la programmation de l'addition. Cependant, le drapeau de report doit être activé dès le début. Le mnémonique pour faire cela est :

Soustraction avec des nombres positifs de seize bits
Considérons la soustraction avec les nombres suivants :

Cette soustraction n’implique pas de complément à deux. Puisque la soustraction en 6502 µP se fait en complément à deux, la soustraction en base deux se fait comme suit :

Le résultat du complément à deux est le même que celui obtenu par la soustraction ordinaire. Cependant, notez que le 1 qui va à la dix-septième position binaire en partant de la droite est ignoré. Le menu et le sous-trahend sont divisés en deux bits de huit chacun. Le complément à deux de 10010110 de l’octet inférieur du sous-trahend est déterminé indépendamment de son octet supérieur et de toute retenue. Le complément à deux de 11101011 de l’octet supérieur du sous-trahend est déterminé indépendamment de son octet inférieur et de toute retenue.

Les 16 bits du menu sont déjà en complément à deux, en commençant par 0 en partant de la gauche. Ainsi, il ne nécessite aucun ajustement en bits. Avec le 6502 µP, l'octet de poids faible du minuend sans aucune modification est ajouté à l'octet de poids faible du complément à deux du sous-trahend. L’octet de poids faible de la fin du menu n’est pas converti en complément à deux car les seize bits de la fin du menu entier doivent déjà être en complément à deux (avec un 0 comme premier bit à gauche). Dans ce premier ajout, un report obligatoire de 1 est ajouté du fait de l'instruction 1=0 SEC.

Dans la soustraction effective actuelle, il y a une retenue de 1 (d'addition) du huitième bit au neuvième bit (en partant de la droite). Puisqu'il s'agit effectivement d'une soustraction, le bit censé être dans l'indicateur de report dans le registre d'état est complété (inversé). Ainsi, le report de 1 devient 0 dans le drapeau C. Dans la deuxième opération, l’octet supérieur du minuend est ajouté à l’octet supérieur du complément à deux du sous-trahend. Le bit d'indicateur de report automatiquement complété du registre d'état (dans ce cas, il est 0) est également ajouté (aux octets supérieurs). Tout 1 qui dépasse le seizième bit en partant de la droite est ignoré.

La prochaine chose est simplement de coder tout ce schéma comme suit :

SECONDE
LDA 0213 $
DCE 0215 $
; pas d'effacement car la valeur de l'indicateur de report inversé est nécessaire
STA 0217 $
LDA 0214 $
DCE 0216 $
STA 0218 $

N'oubliez pas qu'avec le langage assembleur 6502, un point-virgule commence un commentaire qui n'est pas inclus dans la version traduite du programme en mémoire. Les deux nombres de 16 bits pour la soustraction occupent quatre octets de mémoire avec adressage absolu ; deux par nombre (la mémoire est une série d'octets). Ces entrées ne proviennent pas du clavier. Le résultat de la somme est de deux octets et doit également être placé en mémoire à un endroit différent. Cette sortie ne va pas au moniteur ou à l’imprimante ; ça va à la mémoire. Cela donne un total de 6 dix = 6 16 octets d'entrées et de sorties à placer dans la mémoire (RAM).

Avant qu'un programme soit exécuté, il doit d'abord être en mémoire. En regardant le code du programme, on peut voir que les instructions sans commentaire constituent 19 dix = 13 16 octets. Étant donné que tous les programmes de ce chapitre commencent à l'emplacement mémoire de 0200 $, le programme passe de l'emplacement d'octet $0200 dans la mémoire à l'emplacement d'octet $0200 + 13 $ – 1 $ = 0212 $ (en commençant à partir de 0200 $ et non de 0201 $). Cette plage n'inclut pas la région des octets d'entrée et de sortie. Les deux numéros d'entrée prennent 4 octets et le numéro de sortie prend 2 octets. L'ajout des 6 octets pour les numéros d'entrée et de sortie donne la plage du programme qui se termine à 0212 $ + 6 $ = 0218 $. La durée totale du programme est de 19 16 = 25 dix .

L'octet inférieur du menu doit être dans l'adresse $0213, et l'octet supérieur du même menu doit être dans l'adresse $0214 – petit boutisme. De même, l'octet inférieur du sous-trahend doit être dans l'adresse $0215, et l'octet supérieur du même sous-trahend doit être dans l'adresse $0216 – petit boutisme. L'octet inférieur du résultat (différence) doit être dans l'adresse $0217, et l'octet supérieur du même résultat doit être dans l'adresse $0218 – petit boutisme.

L'opcode de 38 16 pour SEC (adressage implicite) se trouve dans l’adresse $0200. Tous les programmes de ce chapitre sont supposés démarrer à l'emplacement mémoire de $0200, annulant tout programme qui aurait été là ; sauf indication contraire. L'opcode pour 'LDA $0213', c'est-à-dire AD 16 , pour LDA (adressage absolu) se trouve à l'emplacement d'octet $0201. L'octet inférieur du menu, qui est 10111111, se trouve à l'emplacement d'octet mémoire $0213. N'oubliez pas que chaque opcode occupe un octet. L'adresse « $0213 » de « LDA $0213 » se trouve dans les emplacements d'octets de $0202 et $0203. L'instruction « LDA $0213 » charge l'octet inférieur du menu dans l'accumulateur.

L'opcode pour 'SBC $0215', c'est-à-dire ED 16 , pour SBC (adressage absolu), se trouve à l'emplacement d'octet $0204. L'octet inférieur du sous-trahend, qui est 01101010, se trouve à l'emplacement d'octet $0215. L'adresse « $0215 » de « ADC $0215 » se trouve dans les emplacements d'octets de $0205 et $0206. L'instruction « SBC $0215 » soustrait l'octet inférieur du sous-trahend de l'octet inférieur du minuend qui est déjà dans l'accumulateur. Il s’agit d’une soustraction du complément à deux. Le résultat est remis dans l'accumulateur. Le complément (inversion) de toute retenue après le huitième bit est envoyé à l'indicateur de retenue du registre d'état. Cet indicateur de report ne doit pas être effacé avant la deuxième soustraction avec les octets supérieurs. Cette retenue est ajoutée automatiquement à la soustraction des octets supérieurs.

Le commentaire prend le 57 suivant dix = 3916 16 octets. Cependant, cela ne reste que dans le fichier texte « .asm ». Il n'atteint pas la mémoire. Il est supprimé par la traduction effectuée par l'assembleur (un programme).

Pour l'instruction suivante qui est « STA $0217 », l'opcode de STA, soit 8D 16 (adressage absolu), se trouve à l'emplacement d'octet $0207. L'adresse « $0217 » de « STA $0217 » se trouve dans les emplacements mémoire de $0208 et $0209. L'instruction « STA $0217 » copie le contenu de huit bits de l'accumulateur vers l'emplacement mémoire de $0217.

L'octet supérieur du menu inférieur, qui est 00101010, se trouve dans l'emplacement mémoire de 0214 $, et l'octet supérieur du sous-traitement, qui est 00010101, se trouve dans l'emplacement d'octet de 0216 $. L'opcode pour 'LDA $0214', c'est-à-dire AD 16 pour LDA (adressage absolu), se trouve à l’emplacement d’octet $020A. L'adresse « $0214 » de « LDA $0214 » se trouve aux emplacements de $020B et $020C. L'instruction « LDA $0214 » charge l'octet supérieur du menu dans l'accumulateur, effaçant tout ce qui se trouve dans l'accumulateur.

L'opcode pour 'SBC $0216', c'est-à-dire ED 16 pour SBC (adressage absolu), se trouve à l’emplacement d’octet $020D. L'adresse « $0216 » de « SBC $0216 » se trouve dans les emplacements d'octets de $020E et $020F. L'instruction « SBC $0216 » soustrait l'octet supérieur du sous-trahend de l'octet supérieur du minuend (complément à deux) qui est déjà dans l'accumulateur. Le résultat est remis dans l’accumulateur. S'il y a une retenue de 1 pour cette deuxième soustraction, son complément est placé automatiquement dans la cellule de retenue du registre d'état. Bien que le report au-delà du seizième bit (à gauche) ne soit pas requis pour ce problème, il est bon de vérifier si le report du complément se produit en vérifiant l'indicateur de report.

Pour la prochaine et dernière instruction qui est le « STA $0218 », l'opcode de STA, soit 8D 16 (adressage absolu), se trouve à l'emplacement d'octet $0210. L'adresse « $0218 » de « STA $0218 » se trouve dans les emplacements mémoire de $0211 et $0212. L'instruction « STA $0218 » copie le contenu de huit bits de l'accumulateur vers l'emplacement mémoire de $0218. Le résultat de la soustraction avec les deux nombres de seize bits est 0001010101010101 avec l'octet inférieur de 01010101 dans l'emplacement mémoire de 0217 $ et l'octet supérieur de 00010101 dans l'emplacement mémoire de 0218 $ – petit boutisme.

Le 6502 µP dispose de circuits uniquement pour l'addition, et indirectement pour la soustraction du complément à deux. Il ne dispose pas de circuits de multiplication et de division. Pour effectuer la multiplication et la division, un programme en langage assembleur avec des détails, y compris le déplacement des produits partiels et des dividendes partiels, doit être écrit.

4.4 Opérations logiques

Dans le 6502 µP, le mnémonique pour OR est ORA et le mnémonique pour OR exclusif est EOR. Notez que les opérations logiques n'ont pas d'adressage implicite. L'adressage implicite ne prend aucun opérande. Chacun des opérateurs logiques doit prendre deux opérandes. Le premier est dans l'accumulateur et le second est dans la mémoire ou dans l'instruction. Le résultat (8 bits) est de retour dans l'accumulateur. Le premier de l'accumulateur y est soit placé par une instruction immédiate, soit copié de la mémoire avec adressage absolu. Dans cette section, seul l’adressage de page zéro est utilisé à des fins d’illustration. Ces opérateurs logiques sont tous des opérateurs bit à bit.

ET
Le tableau suivant illustre le ET au niveau du bit en binaire, hexadécimal et décimal :

Tous les programmes de ce chapitre doivent démarrer à l'emplacement d'octet mémoire de $0200. Cependant, les programmes de cette section sont en page zéro, dans le but d'illustrer l'utilisation de la page zéro sans l'octet supérieur de 00000000. 2 . Le AND précédent peut être codé comme suit :

LDA #$9A ; pas de mémoire – adressage immédiat
ET #$CD ; pas de mémoire – adressage immédiat
STA 30 $ ; stocke 88 $ à 0030 $ de base zéro

OU
Le tableau suivant illustre le OU au niveau du bit en binaire, hexadécimal et décimal :

LDA #$9A ; pas de mémoire – adressage immédiat
ORA #$CD ; pas de mémoire – adressage immédiat
STA 30 $ ; stocke $CF à 0030 $ de base zéro

GRATUIT
Le tableau suivant illustre le Bitwise XOR en binaire, hexadécimal et décimal :

LDA #$9A ; pas de mémoire – adressage immédiat
RAP #$CD ; pas de mémoire – adressage immédiat
STA 30 $ ; stocke 57 $ à 0030 $ de base zéro

4.5 Opérations de décalage et de rotation

Les mnémoniques et les opcodes pour les opérateurs de décalage et de rotation sont :

ASL : décaler vers la gauche d'un bit de l'accumulateur ou de l'emplacement mémoire, en insérant 0 dans la cellule libérée la plus à droite.

LSR : décalez vers la droite un bit de l'accumulateur ou de l'emplacement mémoire, en insérant 0 dans la cellule libérée la plus à gauche.
ROL : faites pivoter un bit à gauche de l'accumulateur ou de l'emplacement mémoire, en insérant le bit qui est supprimé à gauche dans la cellule libérée la plus à droite.
ROR : faites pivoter un bit à droite de l'accumulateur ou de l'emplacement mémoire, en insérant le bit qui est supprimé à droite dans la cellule libérée la plus à gauche.

Pour effectuer un décalage ou une rotation avec l'accumulateur, l'instruction ressemble à ceci :

LSR A

Celui-ci utilise un autre mode d'adressage appelé mode d'adressage accumulateur.

Pour effectuer un décalage ou une rotation avec un emplacement mémoire d'octets, l'instruction ressemble à ceci :

ROR 2 BCD $

Où 2BCD est l'emplacement mémoire.

Notez qu'il n'existe pas de mode d'adressage immédiat ou implicite pour le déplacement ou la rotation. Il n'y a pas de mode d'adressage immédiat car cela ne sert à rien de décaler ou de faire pivoter un numéro qui reste uniquement dans l'instruction. Il n'y a pas de mode d'adressage implicite car les concepteurs du 6502 µP souhaitent que seul le contenu de l'accumulateur (registre A) ou un emplacement d'octet de mémoire soit décalé ou tourné.

4.6 Mode d'adressage relatif

Le microprocesseur incrémente toujours (de 1, 2 ou 3 unités) le compteur de programme (PC) pour pointer vers la prochaine instruction à exécuter. Le 6502 µP possède une instruction dont le mnémonique est BVS qui signifie Branch on Overflow Set. Le PC se compose de deux octets. Cette instruction amène le PC à avoir une adresse mémoire différente pour l'instruction suivante à exécuter ne résultant pas d'un incrément normal. Pour ce faire, il ajoute ou soustrait une valeur, appelée décalage, au contenu du PC. Ainsi, le PC pointe alors vers un emplacement mémoire différent (ramifié) pour que l'ordinateur puisse continuer à s'exécuter à partir de là. Le décalage est un entier compris entre -128 dix au +127 dix (complément à deux). Ainsi, le décalage peut faire avancer le saut dans la mémoire. S'il est positif ou en retard dans la mémoire, ou s'il est négatif.

L'instruction BVS ne prend qu'un seul opérande qui est le décalage. BVS utilise l'adressage relatif. Considérez l'instruction suivante :

BVS $7F

En base deux, 7F H est 01111111 2 = 127 dix . Supposons que le contenu du PC pour l’instruction suivante soit de 0 300 $. L’instruction BVS fait ajouter 7F$ (un nombre positif déjà en complément à deux) à 0300$ pour donner 037F$. Ainsi, au lieu que l'instruction suivante soit exécutée à l'emplacement mémoire de $0300, elle se trouve à l'emplacement mémoire de $037F (environ une demi-page de différence).

Il existe d'autres instructions de branchement, mais BVS est une très bonne méthode à utiliser pour illustrer l'adressage relatif. L'adressage relatif concerne les instructions de branchement.

4.7 Adressage indexé et adressage indirect séparément

Ces modes d'adressage permettent au 6 502 µP de gérer d'énormes quantités de données en peu de temps avec un nombre réduit d'instructions. Il existe des emplacements de 64 Ko pour toute la mémoire du Comodore-64. Ainsi, pour accéder à n’importe quel emplacement d’octet, de 16 bits, il faut deux octets. La seule exception à la nécessité de deux octets concerne la page zéro où l'octet supérieur de $00 est omis pour économiser l'espace occupé par l'instruction dans la mémoire. Avec un mode d'adressage sans page zéro, les octets supérieurs et inférieurs de l'adresse mémoire 16 bits sont pour la plupart indiqués d'une manière ou d'une autre.

Adressage indexé de base

Adressage d'index absolu
N'oubliez pas que le registre X ou Y est appelé registre d'index. Considérez l'instruction suivante :

MDL $C453,X

Supposons que la valeur de 6 H est dans le registre X. Notez que 6 n’est tapé nulle part dans l’instruction. Cette instruction ajoute la valeur de 6H à C453 H qui fait partie de l'instruction tapée dans le fichier texte qui reste à assembler – C453 H + 6 H = C459 H . LDA signifie charger un octet dans l'accumulateur. L'octet à charger dans l'accumulateur provient de l'adresse $C459. Le $C459 qui est la somme de $C453 qui est tapé avec l'instruction et 6 H qui se trouve dans le registre X devient l'adresse effective d'où provient l'octet à charger dans l'accumulateur. Si 6 H était dans le registre Y, Y est tapé à la place de X dans l'instruction.

Dans l'instruction dactylographiée, $C453 est connu comme l'adresse de base et le 6 H dans le registre X ou Y est connu sous le nom de partie de comptage ou d'index pour l'adresse effective. L'adresse de base peut faire référence à n'importe quelle adresse d'octet dans la mémoire, et les 256 suivants dix les adresses sont accessibles, en supposant que l'index (ou le nombre) démarré dans le registre X ou Y est 0. N'oubliez pas qu'un octet peut donner une plage continue allant jusqu'à 256 dix nombres (c'est-à-dire 00000000 2 au 11111111 2 ).

Ainsi, l'adressage absolu ajoute tout ce qui est déjà mis (a été mis par une autre instruction) dans le registre X ou Y aux 16 adresses saisies avec l'instruction pour obtenir l'adresse effective. Dans l'instruction tapée, les deux registres d'index se distinguent par X ou Y qui sont tapés après une virgule. X ou Y est tapé ; pas les deux.

Une fois que tout le programme est tapé dans un éditeur de texte et enregistré avec l'extension de nom de fichier « .asm », l'assembleur, qui est un autre programme, doit traduire le programme tapé en ce qui est (chargé) dans la mémoire. L'instruction précédente, qui est « LDA $C453,X », occupe trois emplacements d'octets dans la mémoire, et non cinq.

N'oubliez pas qu'un mnémonique tel que LDA peut avoir plus d'un opcode (octets différents). L'opcode de l'instruction qui utilise le registre X est différent de l'opcode qui utilise le registre Y. L'assembleur sait quel opcode utiliser en fonction de l'instruction saisie. L'opcode d'un octet pour « LDA $C453,X » est différent de l'opcode d'un octet pour « LDA $C453,Y ». En fait, l'opcode pour LDA dans « LDA $C453,X » est BD, et l'opcode pour LDA dans « LDA $C453,9 » est BD.

Si l'opcode pour LDA se trouve à l'emplacement d'octet $0200. Ensuite, l'adresse de 16 bits de $C453 prend le prochain emplacement d'octet dans la mémoire qui est $0201 et $0202. L'octet de code d'opération particulier indique si c'est le registre X ou le registre Y qui est impliqué. Ainsi, l'instruction du langage assemblé qui est « LDA $C453,X » ou « LDA $C453,Y » occupe trois octets consécutifs en mémoire, et non quatre ou cinq.

Adressage indexé de page zéro
L'adressage d'index de page zéro est comme l'adressage d'index absolu décrit précédemment, mais l'octet cible doit être uniquement sur la page zéro (de 0000 $ à 00FF $). Désormais, lorsqu'il s'agit de la page zéro, l'octet le plus élevé qui est toujours 00 H pour les emplacements mémoire est généralement évité. Ainsi, il est normalement mentionné que la page zéro commence de 00$ à FF. Et donc, l’instruction précédente de « LDA $C453,X » est :

MDL 53,X $

Le $C4, un octet supérieur qui fait référence à une page au-dessus de la page zéro, ne peut pas être utilisé dans cette instruction car il place l'octet cible attendu à charger dans l'octet accumulé en dehors et au-dessus de la page zéro.

Lorsque la valeur saisie dans l'instruction est ajoutée à la valeur dans le registre d'index, la somme ne doit pas donner un résultat supérieur au zéro de la page (FF H ). Il est donc hors de question d’avoir une instruction du type « LDA $FF, X » et une valeur du type FF H dans le registre d'index car FF H +FF H = 200 H qui est le premier octet ($0200) de la page 2 (troisième page) dans la mémoire, est très éloigné de la page 0. Ainsi, avec un adressage indexé de page zéro, l'adresse effective doit se trouver dans la page zéro.

Adressage indirect

Saut d'adressage absolu
Avant de discuter de l'adressage indirect absolu, il est bon d'examiner d'abord l'adressage absolu JMP. Supposons que l’adresse qui a la valeur d’intérêt (octet cible) soit 8 765 $. Il s'agit de 16 bits composés de deux octets : l'octet le plus élevé qui est 87 H et l'octet inférieur qui est 65 H . Ainsi, les deux octets pour 8 765 $ sont placés dans le PC (compteur de programme) pour l'instruction suivante. Ce qui est tapé dans le programme en langage assembleur (fichier) est :

JMP8 765 $

Le programme en cours d'exécution dans la mémoire passe de l'adresse à laquelle il a accédé à 8 765 $. Le mnémonique JMP comporte trois opcodes : 4C, 6C et 7C. L'opcode pour cet adressage absolu est 4C. L'opcode pour l'adressage indirect absolu JMP est 6C (reportez-vous aux illustrations suivantes).

Adressage indirect absolu
Ceci est utilisé uniquement avec l'instruction de saut (JMP). Supposons que l’adresse contenant l’octet qui vous intéresse (octet cible) soit 8 765 $. Il s'agit de 16 bits composés de deux octets : l'octet le plus élevé qui est 87 H et l'octet inférieur qui est 65 H . Avec l'adressage indirect absolu, ces deux octets sont en fait situés dans deux emplacements d'octets consécutifs ailleurs dans la mémoire.

Supposons qu'ils se trouvent dans les emplacements mémoire $0210 et $0211. Ensuite, l'octet de poids faible de l'adresse d'intérêt qui est 65 H est dans l'adresse $0210, et l'octet supérieur qui est 87 H est à l'adresse $0211. Cela signifie que l'octet de mémoire d'intérêt inférieur va à l'adresse consécutive inférieure, et l'octet de mémoire d'intérêt supérieur va à l'adresse consécutive supérieure – petit boutisme.

L'adresse 16 bits peut faire référence à deux adresses consécutives dans la mémoire. Dans cette optique, l'adresse 0210 $ fait référence aux adresses 0210 $ et 0211 $. La paire d'adresses $0210 et $0211 contient l'adresse ultime (16 bits de deux octets) de l'octet cible, l'octet inférieur étant de 65. H en $0210 et l'octet supérieur de 87 H en 0211 $. Ainsi, l’instruction de saut saisie est :

JMP (0210 $)

Le mnémonique JMP comporte trois opcodes : 4C, 6C et 7C. L'opcode pour l'adressage indirect absolu est 6C. Ce qui est tapé dans le fichier texte est « JMP ($0210) ». A cause des parenthèses, l'assembleur (traducteur) utilise l'opcode 6C pour JMP, et non 4C ou 7C.

Avec l’adressage indirect absolu, il existe en réalité trois régions mémoire. La première région peut être constituée des emplacements d'octets $0200, $0201 et $0202. Celui-ci contient les trois octets pour l'instruction « JMP ($0210) ». La deuxième région, qui n'est pas nécessairement voisine de la première, est constituée des deux emplacements d'octets consécutifs $0210 et $0211. Il s'agit ici de l'octet de poids faible (0210 $) qui est saisi dans l'instruction du programme en langage assembleur. Si l'adresse d'intérêt est $8765, l'octet inférieur de 65 H se trouve à l'emplacement d'octet $0210 et l'octet supérieur de 87 H se trouve à l'emplacement d'octet $0211. La troisième région comprend un seul emplacement d'octet. Il s'agit de l'adresse $8765 pour l'octet ciblé (ultime octet d'intérêt). La paire d'adresses consécutives, 0210 $ et 0211 $, contient le pointeur 8 765 $ qui est l'adresse qui nous intéresse. Après l'interprétation informatique, c'est 8765$ qui vont dans le PC (Program Counter) pour accéder à l'octet cible.

Adressage indirect zéro page
Cet adressage est le même que l'adressage indirect absolu, mais le pointeur doit être en page zéro. L’adresse de l’octet inférieur de la région du pointeur correspond à ce qui se trouve dans l’instruction saisie comme suit :

JMP (50 $)

L'octet le plus élevé du pointeur se trouve à l'emplacement d'octet $51. Il n'est pas nécessaire que l'adresse effective (pointée) se trouve à la page zéro.

Ainsi, avec l'adressage d'index, la valeur dans un registre d'index est ajoutée à l'adresse de base donnée dans l'instruction pour avoir l'adresse effective. L'adressage indirect utilise un pointeur.

4.8 Adressage indirect indexé

Adressage indirect indexé absolu
Ce mode d'adressage est utilisé uniquement avec l'instruction JMP.
Avec l'adressage indirect absolu, il existe la valeur pointée (octet) avec ses propres adresses d'octets consécutives. Ces deux adresses consécutives forment le pointeur devant se trouver dans la région de pointeur de deux octets consécutifs dans la mémoire. L'octet inférieur de la région du pointeur correspond à ce qui est saisi dans l'instruction entre parenthèses. Le pointeur est l'adresse de la valeur pointée. Dans la situation précédente, 8 765 $ est l’adresse de la valeur indiquée. Le $0210 (suivi de $0211) est l'adresse dont le contenu est $8765 qui est le pointeur. Avec le mode d'adressage indirect absolu, c'est ($0210) qui est saisi dans le programme (fichier texte), parenthèses comprises.

D'autre part, avec le mode d'adressage indirect indexé absolu, l'octet d'adresse inférieur pour la région du pointeur est formé en ajoutant la valeur du registre X à l'adresse saisie. Par exemple, si le pointeur se trouve à l’emplacement d’adresse $0210, l’instruction saisie peut ressembler à ceci :

JMP (020$A,X)

Où le registre X a la valeur de 6 H . 020A H + 6 H = 0210 H . Le registre Y n'est pas utilisé avec ce mode d'adressage.

Adressage indirect indexé par page zéro
Ce mode d'adressage utilise le registre X et non le registre Y. Avec ce mode d'adressage, il y a toujours la valeur pointée et le pointeur dans sa région de pointeur d'adresse à deux octets. Il doit y avoir deux octets consécutifs dans la page zéro pour le pointeur. L'adresse saisie dans l'instruction est une adresse d'un octet. Cette valeur est ajoutée à la valeur du registre X et toute retenue est rejetée. Le résultat pointe vers la région de pointeur de la page 0. Par exemple, si l'adresse d'intérêt (pointée) est $8765 et qu'elle se trouve dans les emplacements d'octets de $50 et $51 de la page 0, et que la valeur dans le registre X est de 30 $, le l'instruction tapée ressemble à ceci :

LDA (20,X $)

Parce que 20$ + 30$ = 50$.

Adressage indexé indirect
Ce mode d'adressage utilise le registre Y et non le registre X. Avec ce mode d'adressage, il y a toujours la valeur pointée et la région du pointeur, mais le contenu de la région du pointeur fonctionne différemment. Il doit y avoir deux octets consécutifs dans la page zéro pour la région du pointeur. L'adresse inférieure de la région du pointeur est saisie dans l'instruction. Ce nombre (paire d'octets) contenu dans la région du pointeur est ajouté à la valeur du registre Y pour avoir le pointeur réel. Par exemple, supposons que l'adresse d'intérêt (pointée) soit $8765, que la valeur de 6H soit dans le registre Y et que le nombre (deux octets) soit à l'adresse de 50. H et 51 H . Les deux octets ensemble valent 875F$ puisque 875F$ + 6$ = 8765$. L'instruction tapée ressemble à ceci :

LDA (50 $), Y

4.9 Instructions d'incrémentation, de décrémentation et de test-BIT

Le tableau suivant montre les opérations des instructions d'incrémentation et de décrémentation :

L'INA et la DEA incrémentent et décrémentent respectivement l'accumulateur. C'est ce qu'on appelle l'adressage de l'accumulateur. INX, DEX, INY et DEY concernent respectivement les registres X et Y. Ils ne prennent aucun opérande. Ils utilisent donc le mode d'adressage implicite. L'incrément signifie ajouter 1 au registre ou à l'octet de mémoire. Décrémenter signifie soustraire 1 du registre ou de l’octet de mémoire.

Les INC et DEC incrémentent et décrémentent respectivement un octet de mémoire (et non un registre). L'utilisation de l'adressage par page zéro au lieu de l'adressage absolu permet d'économiser la mémoire de l'instruction. L'adressage de page zéro est inférieur d'un octet à l'adressage absolu de l'instruction dans la mémoire. Cependant, le mode d'adressage de la page zéro n'affecte que la page zéro.

L'instruction BIT teste les bits d'un octet en mémoire avec les 8 bits de l'accumulateur, mais ne change aucun des deux. Seuls certains indicateurs du registre d'état du processeur « P » sont activés. Les bits de l'emplacement mémoire spécifié sont logiquement AND avec ceux de l'accumulateur. Ensuite, les bits d'état suivants sont définis :

  • N qui est le bit 7 et le dernier bit (à gauche) du registre d'état, reçoit le bit 7 de l'emplacement mémoire avant l'opération AND.
  • V qui est le bit 6 du registre d'état reçoit le bit 6 de l'emplacement mémoire avant l'opération AND.
  • Le drapeau Z du registre d'état est activé (fait 1) si le résultat du ET est zéro (00000000 2 ). Sinon, il est effacé (mis à 0).

4.10 Instructions de comparaison

Les mnémoniques des instructions de comparaison pour le 6 502 µP sont CMP, CPX et CPY. Après chaque comparaison, les drapeaux N, Z et C du registre d'état du processeur « P » sont affectés. Le drapeau N est activé (fait 1) lorsque le résultat est un nombre négatif. Le drapeau Z est activé (fait 1) lorsque le résultat est un zéro (000000002). L'indicateur C est activé (mis à 1) lorsqu'il y a une retenue du huit au neuvième bit. Le tableau suivant donne une illustration détaillée

Cela signifie « supérieur à ». Avec cela, le tableau comparatif devrait être explicite.

4.11 Instructions de saut et de branchement

Le tableau suivant résume les instructions de saut et de branchement :

L'instruction JMP utilise l'adressage absolu et indirect. Le reste des instructions du tableau sont des instructions de branchement. Ils utilisent uniquement l'adressage relatif avec le 6502 µP. Ainsi, le tableau devient explicite s’il est lu de gauche à droite et de haut en bas.

Notez que les branches ne peuvent être appliquées qu'aux adresses comprises entre -128 et +127 octets à partir de l'adresse donnée. Il s'agit d'un adressage relatif. Pour les instructions JMP et de branchement, le compteur de programme (PC) est directement affecté. Le 6502 µP ne permet pas les branchements vers une adresse absolue, bien que le saut puisse effectuer l'adressage absolu. L'instruction JMP n'est pas une instruction de branchement.

Note: L'adressage relatif est utilisé uniquement avec les instructions de branchement.

4.12 La zone de pile

Un sous-programme est comme l'un des programmes courts précédents pour additionner ou soustraire deux nombres. La zone de pile dans la mémoire commence entre 0100 $ et 01FF $ inclusivement. Cette zone est simplement appelée la pile. Lorsque le microprocesseur exécute un saut vers l'instruction de sous-programme (JSR – voir la discussion suivante), il doit savoir où revenir une fois terminé. Le 6502 µP conserve ces informations (adresse de retour) dans une mémoire faible de 0100 $ à 01FF $ (la zone de pile) et utilise le contenu du registre du pointeur de pile qui est « S » dans le microprocesseur comme pointeur (9 bits) vers la dernière adresse renvoyée. qui est stocké dans la page 1 ($0100 à $01FF) de la mémoire. La pile s'agrandit à partir de $01FF et permet d'imbriquer les sous-programmes jusqu'à 128 niveaux de profondeur.

Une autre utilisation du pointeur de pile consiste à gérer les interruptions. Le 6502 µP possède des broches étiquetées IRQ et NMI. Il est possible que certains petits signaux électriques soient appliqués à ces broches et amènent le 6502 µP à arrêter d'exécuter un programme et à en exécuter un autre. Dans ce cas, le premier programme est interrompu. Comme les sous-programmes, les segments de code d'interruption peuvent être imbriqués. Le traitement des interruptions est abordé dans le chapitre suivant.

Note : Le pointeur de pile a 8 bits pour l'adresse de l'octet inférieur pour adressage des emplacements de $0100 à $01FF. L'octet supérieur de 00000001 2 est assumé.

Le tableau suivant donne les instructions qui associent le pointeur de pile « S » avec les registres A, X, Y et P à la zone de pile de la mémoire :

4.13 Appel et retour de sous-programme

Un sous-programme est un ensemble d'instructions qui atteignent un objectif particulier. Le programme d'addition ou de soustraction précédent est un sous-programme très court. Les sous-programmes sont parfois simplement appelés routines. L’instruction pour appeler un sous-programme est :

JSR : passer au sous-programme

L'instruction à renvoyer d'un sous-programme est :

RTS : Retour du sous-programme

Le microprocesseur a tendance à exécuter en permanence les instructions en mémoire, les unes après les autres. Supposons que le microprocesseur exécute actuellement un segment de code et qu'il rencontre une instruction de saut (JMP) pour aller exécuter un segment de code qui est codé derrière celui qu'il pourrait déjà avoir exécuté. Il exécute ce segment de code derrière et continue d'exécuter tous les segments de code (instructions) suivant le segment de code derrière, jusqu'à ce qu'il réexécute à nouveau le segment de code actuel et continue ci-dessous. JMP ne pousse pas l'instruction suivante vers la pile.

Contrairement à JMP, JSR pousse l'adresse de l'instruction suivante après lui depuis le PC (compteur de programme) vers la pile. La position de pile de cette adresse est placée dans le pointeur de pile « S ». Lorsqu'une instruction RTS est rencontrée (exécutée) dans le sous-programme, l'adresse qui est poussée sur la pile retire la pile et le programme reprend à cette adresse extraite qui est l'adresse d'instruction suivante juste avant l'appel du sous-programme. La dernière adresse supprimée de la pile est envoyée au compteur du programme. Le tableau suivant donne les détails techniques des instructions JSR et RTS :

Consultez l'illustration suivante pour connaître les utilisations de JSR et RTS :

4.14 Un exemple de boucle de compte à rebours

Le sous-programme suivant compte à rebours de $FF à $00 (total de 256 dix compte):

démarrer LDX #$FF ; charger X avec $FF = 255
boucle DEX ; X = X – 1
Boucle BNE ; si X est différent de zéro alors allez en boucle
RTS ; retour

Chaque ligne a un commentaire. Les commentaires ne sont jamais mis en mémoire pour exécution. L'assembleur (traducteur) qui convertit un programme en ce qu'il est en mémoire pour l'exécution (en cours d'exécution) supprime toujours les commentaires. Un commentaire commence par « ; » . Le « début » et la « boucle » dans ce programme sont appelés étiquettes. Une étiquette identifie (le nom) de l'adresse de l'instruction. Si l'instruction est une instruction à un seul octet (adressage implicite), l'étiquette est l'adresse de cette instruction. Si l'instruction est une instruction multi-octets, l'étiquette identifie le premier octet de l'instruction multi-octets. La première instruction de ce programme se compose de deux octets. En supposant qu'elle commence à l'adresse $0300, l'adresse $0300 peut être remplacée par « start » dans le programme. La deuxième instruction (DEX) est une instruction à un seul octet et doit être à l'adresse $0302. Cela signifie que l'adresse $0302 peut être remplacée par « boucle », en bas du programme, ce qui est en fait le cas dans « boucle BNE ».

« Boucle BNE » désigne le branchement vers l'adresse donnée lorsque l'indicateur Z du registre d'état est 0. Lorsque la valeur dans le registre A ou X ou Y est 00000000. 2 , en raison de la dernière opération, le drapeau Z est 1 (set). Ainsi, même si la valeur est 0 (et non 1), les deuxième et troisième instructions du programme sont répétées dans cet ordre. Dans chaque séquence répétée, la valeur (nombre entier) dans le registre X est diminuée de 1. DEX signifie X = X – 1. Lorsque la valeur dans le registre X est 00 $ = 00000000 2 , Z devient 1. A ce stade, il n’y a plus de répétition des deux instructions. La dernière instruction RTS du programme, qui est une instruction à un seul octet (adressage implicite), revient du sous-programme. L'effet de cette instruction est de faire en sorte que le compteur de programme adresse dans la pile le code à exécuter avant l'appel du sous-programme et de revenir au compteur de programme (PC). Cette adresse est l'adresse de l'instruction qui doit être exécutée avant l'appel du sous-programme.

Note: Lors de l'écriture d'un programme en langage assembleur pour le 6502 µP, seule une étiquette doit commencer au début d'une ligne ; tout autre code de ligne doit être décalé d'au moins un espace vers la droite.

Appeler un sous-programme
En ignorant l'espace mémoire occupé par les étiquettes précédentes, le programme prend 6 octets d'emplacements consécutifs dans la mémoire (RAM) de 0300 $ à 0305 $. Dans ce cas, le programme est :

LDX #$FF ; charger X avec $FF = 255
DEX ; X = X – 1
0302 BNE ; si X est différent de zéro alors allez en boucle
RTS ; retour

À partir de l’adresse $0200 dans la mémoire peut être l’appel du sous-programme. L'instruction d'appel est :

Démarrage JSR ; le début est l'adresse 0300 $, c'est-à-dire JSR 0300 $

Le sous-programme et son appel correctement écrits dans le fichier de l'éditeur de texte sont :

démarrer LDX #$FF ; charger X avec $FF = 255
boucle DEX ; X = X – 1

Boucle BNE ; si X est différent de zéro alors allez en boucle
RTS ; retour

Démarrage JSR : passez à la routine commençant à 0300 $

Désormais, il peut y avoir plusieurs sous-programmes dans un seul programme long. Tous ne peuvent pas porter le nom de « start ». Ils devraient avoir des noms différents. En fait, aucun d’entre eux ne pourrait porter le nom de « start ». « Démarrer » est utilisé ici à des fins pédagogiques.

4.15 Traduire un programme

Traduire un programme ou l’assembler signifie la même chose. Considérons le programme suivant :

démarrer LDX #$FF : charger X avec $FF = 255
boucle DEX : X = X – 1
Boucle BNE : si X est différent de zéro alors passez à la boucle
RTS : retour
Démarrage JSR : passez à la routine commençant à 0300 $

Il s'agit du programme qui a été écrit précédemment. Il se compose du sous-programme, du démarrage et de l'appel au sous-programme. Le programme compte à rebours de 255 dix à 0 dix . Le programme commence à l'adresse de début de l'utilisateur, soit 0200 $ (RAM). Le programme est saisi dans un éditeur de texte et enregistré sur le disque. Il porte un nom comme « sample.asm », où « sample » est le nom choisi par le programmeur mais l'extension « .asm » du langage assembleur doit être associée au nom de fichier.

Le programme assemblé est produit par un autre programme appelé assembleur. L'assembleur est fourni par le fabricant du 6502 µP ou par un tiers. L'assembleur reproduit le programme de telle manière qu'il se trouve dans la mémoire (RAM) lors de son exécution (run).

Supposons que l'instruction JSR commence à l'adresse $0200 et que le sous-programme commence à l'adresse $0300. L'assembleur supprime tous les commentaires et espaces blancs. Les commentaires et les espaces blancs gaspillent la mémoire qui est toujours rare. Une éventuelle ligne vide entre le segment de code de sous-programme précédent et l'appel de sous-programme est un exemple d'espace. Le fichier assemblé est toujours enregistré sur le disque et son nom ressemble à « sample.exe ». Le « échantillon » est le nom choisi par le programmeur, mais l'extension « .exe » doit être là pour indiquer qu'il s'agit d'un fichier exécutable.

Le programme assemblé peut être documenté comme suit :

Produire un document comme celui-ci s’appelle un assemblage à la main. Notez que les commentaires de ce document n'apparaissent pas en mémoire (pour exécution). La colonne d'adresse du tableau indique les adresses de début des instructions dans la mémoire. Notez que « JSR start » qui est « JSR $0300 », qui devrait être codé comme « 20 03 00 », est en fait codé comme « 20 00 03 », l'adresse d'octet de mémoire inférieure prenant l'octet de poids faible dans la mémoire et le adresse d'octet de mémoire supérieure prenant l'octet de mémoire supérieur – petite endianité. L'opcode pour JSR est 20 16 .

Notez que le décalage vers une instruction de branchement telle que BNE est un nombre complémentaire à deux compris entre 128 et 128. dix au + 127 dix . Ainsi, « boucle BNE » signifie « BNE -1 dix » qui est en fait « D0 FF » sous la forme de code FF 16 est -1 en complément à deux qui s'écrit = 11111111 en base deux. Le programme assembleur remplace les étiquettes et les champs par des nombres hexadécimaux réels (les nombres hexadécimaux sont des nombres binaires regroupés en quatre bits). Les adresses réelles où commence chaque instruction sont en fait incluses.

Note: L'instruction « JSR start » est remplacée par des instructions plus courtes qui envoient le contenu actuel (octets de poids fort et octets de poids faible) du compteur de programme à la pile avec le pointeur de pile qui est décrémenté deux fois (une fois pour l'octet de poids fort et une fois pour l'octet de poids faible) et puis recharge le PC avec l'adresse $0300. Le pointeur de pile pointe désormais vers $00FD, en supposant qu'il soit initialisé à $01FF.

De plus, l'instruction RTS est remplacée par un certain nombre d'instructions plus courtes qui incrémentent le pointeur de pile « S » deux fois (une fois pour l'octet de poids faible et une fois pour l'octet de poids fort) et extraient les deux octets d'adresse correspondants du pointeur de pile vers le PC pour la prochaine instruction.

Note: Un texte d'étiquette ne doit pas comporter plus de 8 caractères.

La « boucle BNE » utilise l'adressage relatif. Cela signifie ajouter -3 dix au prochain contenu du compteur de programme de 0305 $. Les octets pour « boucle BNE » sont « D0 FD » où FD est le complément à deux de -3 dix .

Remarque : Ce chapitre ne présente pas toutes les instructions du 6502 µP. Toutes les instructions et leurs détails se trouvent dans le document intitulé « Famille de microprocesseurs SY6500 8 bits ». Il existe un fichier PDF portant le nom « 6502.pdf » pour ce document, disponible gratuitement sur Internet. Le 6502 µP décrit dans ce document est 65C02.

4.16 Interruptions

Les signaux de tout appareil connecté aux ports externes (surface verticale) du Commodore 64 doivent passer par les circuits (CI) CIA 1 ou CIA 2 avant d'atteindre le microprocesseur 6502. Les signaux du bus de données du 6502 µP doivent passer soit par la puce CIA 1, soit par la puce CIA 2 avant d'atteindre un périphérique externe. CIA signifie Complex Interface Adapter. Dans la figure 4.1 « Schéma fonctionnel de la carte mère Commodore_64 », les blocs d'entrée/sortie représentent le CIA 1 et le CIA 2. Lorsqu'un programme est en cours d'exécution, il peut être interrompu pour exécuter un autre morceau de code avant de continuer. Il y a une interruption matérielle et une interruption logicielle. Pour l'interruption matérielle, il y a deux broches de signal d'entrée vers le 6502 µP. Les noms de ces broches sont IRQ et INM . Ce ne sont pas des lignes de données µP. Les lignes de données pour le µP sont D7, D6, D5, D4, D3, D2, D1 et D0 ; avec D0 pour le bit de poids faible et D7 pour le bit de poids fort.

IRQ signifie Interrupt ReQuest « actif » bas. Cette ligne d'entrée vers le µP est normalement haute, à environ 5 volts. Lorsqu'il descend à environ 0 volt, c'est une demande d'interruption qui signale le µP. Dès que la demande est accordée, la ligne remonte haut. Accorder la demande d'interruption signifie que le µP se branche vers le code (sous-programme) qui gère l'interruption.

INM signifie Interruption non masquable « active » basse. Alors que le code pour IRQ est en cours d'exécution INM peut descendre. Dans ce cas, INM est géré (son propre code est exécuté). Après cela, le code pour IRQ continue. Après le code pour IRQ se termine, le code du programme principal continue. C'est, INM interrompt le IRQ gestionnaire. Le signal pour INM peut toujours être donné au µP même lorsque le µP est inactif et ne gère rien ou n’exécute pas de programme principal.

Note: Il s'agit en fait de la transition du haut vers le bas, INM , C'est le INM signal – nous en reparlerons plus tard. IRQ vient normalement de la CIA 1 et INM vient normalement de la CIA 2. INM , qui signifie Non-Maskable Interrupt, peut être considérée comme une interruption non arrêtable.

Gestion des interruptions
Que la demande émane de IRQ ou INM , l'instruction en cours doit être terminée. Le 6502 ne possède que les registres A, X et Y. Pendant qu'un sous-programme fonctionne, il peut utiliser ces trois registres ensemble. Un gestionnaire d'interruption est toujours un sous-programme, bien qu'il ne soit pas considéré comme tel. Une fois l'instruction en cours terminée, le contenu des registres A, X et Y du 65C02 µP est enregistré dans la pile. L'adresse de la prochaine instruction du Program Counter est également envoyée à la pile. Le µP passe ensuite au code de l'interruption. Après cela, le contenu des registres A, X et Y est ensuite restauré à partir de la pile dans l'ordre inverse vers lequel il a été envoyé.

Exemple de codage pour une interruption
Par souci de simplicité, supposons que la routine pour le µP IRQ l'interruption consiste simplement à additionner les nombres $01 et $02 et à enregistrer le résultat de $03 à l'adresse mémoire de $0400. Le code est :

ISR PHA
PHX
PHY
;
LDA #$01
CDA #$02
ILS COÛTENT 0400 $
;
PLI
PLX
PLA
RTI

ISR est une étiquette et identifie l'adresse mémoire où se trouve l'instruction PHA. ISR signifie Interruption de Service Routine. PHA, PHX et PHY envoient le contenu des registres A, X et Y à la pile dans l'espoir qu'ils seront nécessaires au code (programme) en cours d'exécution juste avant l'interruption. Les trois instructions suivantes constituent le cœur du gestionnaire d'interruptions. Les instructions PLY, PLX et PLA doivent être dans cet ordre et ramènent le contenu des registres Y, X et A. La dernière instruction, qui est RTI, (sans opérande) renvoie la suite de l'exécution à n'importe quel code (programme) en cours d'exécution avant l'interruption. RTI récupère l'adresse de la prochaine instruction du code en cours d'exécution de la pile vers le compteur du programme. RTI signifie ReTurn from Interrupt. Avec cela, la gestion des interruptions (sous-programme) est terminée.

Interruption logicielle
Le principal moyen d'obtenir une interruption logicielle pour le 6502 µP consiste à utiliser l'instruction d'adresse implicite BRK. Supposons que le programme principal est en cours d’exécution et qu’il rencontre l’instruction BRK. À partir de ce point, l’adresse de l’instruction suivante dans le PC doit être envoyée à la pile au fur et à mesure que l’instruction en cours est terminée. Un sous-programme destiné à gérer l'instruction logicielle doit être appelé « suivant ». Ce sous-programme d'interruption doit pousser le contenu des registres A, X et Y vers la pile. Une fois le cœur du sous-programme exécuté, le contenu des registres A, X et Y doit être retiré de la pile vers leurs registres par le sous-programme qui se termine. La dernière instruction de la routine est RTI. Le contenu du PC est également automatiquement extrait de la pile vers le PC grâce à RTI.

Comparaison et contraste des sous-programmes et des routines de service d'interruption
Le tableau suivant compare et oppose la routine de sous-programme et de service d'interruption :

4.17 Résumé des principaux modes d'adressage du 6502

Chaque instruction du 6502 est constituée d'un octet, suivi de zéro ou plusieurs opérandes.

Mode d'adressage immédiat
Avec le mode d'adressage immédiat, après l'opérande, se trouve la valeur et non une adresse mémoire. La valeur doit être précédée de #. Si la valeur est en hexadécimal, le « # » doit être suivi de « $ ». Les instructions d'adressage immédiat pour le 65C02 sont : ADC, AND, BIT, CMP, CPX, CPY, EOR, LDA, LDX, LDY, ORA, SBC. Le lecteur doit consulter la documentation du 65C02 µP afin de savoir comment utiliser les instructions répertoriées ici qui ne sont pas expliquées dans ce chapitre. Un exemple d'instruction est :

LDA #77$

Mode d'adressage absolu
En mode d'adressage absolu, il y a un seul opérande. Cet opérande est l'adresse de la valeur en mémoire (généralement en hexadécimal ou en label). Il y a 64K dix = 65 536 dix adresses mémoire pour le 6502 µP. En règle générale, la valeur d'un octet se trouve à l'une de ces adresses. Les instructions d'adressage absolues pour le 65C02 sont : ADC, AND, ASL, BIT, CMP, CPX, CPY, DEC, EOR, INC, JMP, JSR, LDA, LDX, LDY, LSR, ORA, ROL, ROR, SBC, STA. , STX, STY, STZ, TRB, BST. Le lecteur devra consulter la documentation du 65C02 µP afin de savoir comment utiliser les instructions listées ici, ainsi que pour le reste des modes d'adressage qui ne sont pas expliqués dans ce chapitre. Un exemple d'instruction est :

ILS SONT 1234$

Mode d'adressage implicite
En mode d'adressage implicite, il n'y a pas d'opérande. Tout registre µP impliqué est impliqué par l'instruction. Les instructions d'adressage implicites pour le 65C02 sont : BRK, CLC, CLD, CLI, CLV, DEX, DEY, INX, INY, NOP, PHA, PHP, PHX, PHY, PLA, PLP, PLX, PLY, RTI, RTS, SEC. , SED, SEI, TAX, TAY, TSX, TXA, TXS, TYA. Un exemple d'instruction est :

DEX : Décrémente le registre X d'une unité.

Mode d'adressage relatif
Le mode d'adressage relatif ne concerne que les instructions de branchement. En mode d'adressage relatif, il n'y a qu'un seul opérande. C'est une valeur de -128 dix au +127 dix . Cette valeur est appelée un décalage. En fonction du signe, cette valeur est ajoutée ou soustraite de l'instruction suivante du compteur de programme pour obtenir l'adresse de l'instruction suivante prévue. Les instructions relatives du mode d'adressage sont : BCC, BCS, BEQ, BMI, BNE, BPL, BRA, BVC, BVS. Les exemples d'instructions sont :

BNE $7F : (branche si Z = 0 dans le registre d'état, P)

Ce qui ajoute 127 au compteur du programme actuel (adresse à exécuter) et commence l'exécution de l'instruction à cette adresse. De la même manière:

BEQ $F9 : (branchement si Z = : dans le registre d'état, P)

Ce qui ajoute un -7 au compteur de programme actuel et démarre l'exécution à la nouvelle adresse du compteur de programme. L’opérande est un nombre complémentaire à deux.

Adressage indexé absolu
Dans l'adressage d'index absolu, le contenu du registre X ou Y est ajouté à l'adresse absolue donnée (de 0000 $ à $FFFF, c'est-à-dire de 0 dix au 65536 dix ) pour avoir la véritable adresse. Cette adresse absolue donnée est appelée adresse de base. Si le registre X est utilisé, l'instruction d'assemblage ressemble à ceci :

MDL $C453,X

Si le registre Y est utilisé, cela ressemble à ceci :

MDL $C453,Y

La valeur du registre X ou Y est appelée valeur de comptage ou d'index et peut être comprise entre 00 $ (0 dix ) à FF$ (250 dix ). Cela ne s’appelle pas le décalage.

Les instructions d'adressage d'index absolu sont : ADC, AND, ASL (X uniquement), BIT (avec accumulateur et mémoire, avec X uniquement), CMP, DEC (mémoire et X uniquement), EOR, INC (mémoire et X uniquement), LDA. , LDX, LDY, LSR (X uniquement), ORA, ROL (X uniquement), ROR (X uniquement), SBC, STA, STZ (X uniquement).

Adressage indirect absolu
Ceci est utilisé uniquement avec l'instruction de saut. Avec cela, l'adresse absolue donnée a une adresse de pointeur. L'adresse du pointeur se compose de deux octets. Le pointeur de deux octets pointe vers (est l'adresse de) la valeur d'octet de destination dans la mémoire. Ainsi, l’instruction en langage assembleur est la suivante :

JMP (3 456 $)

Avec les parenthèses, et $13 se trouve à l'emplacement d'adresse de 3456 $ tandis que $EB est à l'emplacement d'adresse de 3457 $ (= 3456 $ + 1). Ensuite, l’adresse de destination est $13EB et $13EB est le pointeur. Le $3456 absolu est entre parenthèses dans l'instruction où 34 est l'octet de poids faible et 56 est l'octet de poids fort.

4.18 Création d'une chaîne avec le langage assembleur 6502 µP

Comme démontré dans le chapitre suivant, après avoir créé un fichier dans la mémoire, le fichier peut être enregistré sur le disque. Le fichier doit recevoir un nom. Le nom est un exemple de chaîne. Il existe de nombreux autres exemples de chaînes en programmation.

Il existe deux manières principales de créer une chaîne de codes ASCII. Dans les deux cas, tous les codes (caractères) ASCII occupent des emplacements d'octets consécutifs en mémoire. Dans l'un des cas, cette séquence d'octets est précédée d'un octet entier qui correspond à la longueur (nombre de caractères) de la séquence (chaîne). Dans l'autre sens, la séquence de caractères est suivie (immédiatement suivie) par l'octet Null qui est 00. 16 , soit 00 $. La longueur de la chaîne (nombre de caractères) n'est pas indiquée de cette autre manière. Le caractère Null n'est pas utilisé dans le premier sens.

Par exemple, considérons le « Je t’aime ! » chaîne sans les guillemets. La longueur ici est de 11 ; un espace compte pour un octet (caractère) ASCII. Supposons que la chaîne doit être placée en mémoire avec le premier caractère étant à l'adresse $0300.

Le tableau suivant montre le paramètre de mémoire de chaîne lorsque le premier octet est 11. dix = 0B 16 :

Le tableau suivant montre le paramètre de mémoire de chaîne lorsque le premier octet est « I » et le dernier octet est Null ($00) :

L'instruction suivante peut être utilisée pour commencer à créer la chaîne :

ILS COÛTENT 0300 $

Supposons que le premier octet se trouve dans l’accumulateur qui doit être envoyé à l’adresse $0300. Cette instruction est vraie dans les deux cas (les deux types de chaînes).

Après avoir inséré tous les caractères dans les cellules mémoire, un par un, la chaîne peut être lue à l'aide d'une boucle. Dans le premier cas, le nombre de caractères après la longueur est lu. Pour le deuxième cas, les caractères sont lus à partir de « I » jusqu'à ce que le caractère Null qui est « Null » soit rencontré.

4.19 Création d'un tableau avec le langage assembleur 6502 µP

Un tableau d'entiers à un octet se compose d'emplacements d'octets de mémoire consécutifs avec les entiers. Ensuite, il y a un pointeur qui pointe vers l’emplacement du premier entier. Ainsi, un tableau d’entiers se compose de deux parties : le pointeur et la série d’emplacements.

Pour un tableau de chaînes, chaque chaîne peut se trouver à un endroit différent dans la mémoire. Ensuite, il existe des emplacements mémoire consécutifs avec des pointeurs où chaque pointeur pointe vers le premier emplacement de chaque chaîne. Un pointeur dans ce cas se compose de deux octets. Si une chaîne commence par sa longueur, le pointeur correspondant pointe vers l'emplacement de cette longueur. Si une chaîne ne commence pas par sa longueur mais se termine par un caractère nul, le pointeur correspondant pointe vers l'emplacement du premier caractère de la chaîne. Et il y a un pointeur qui pointe vers l'adresse de l'octet inférieur du premier pointeur de pointeurs consécutifs. Ainsi, un tableau de chaînes se compose de trois parties : les chaînes situées à différents endroits de la mémoire, les pointeurs consécutifs correspondants et le pointeur vers le premier pointeur des pointeurs consécutifs.

4.20 Problèmes

Il est conseillé au lecteur de résoudre tous les problèmes d'un chapitre avant de passer au chapitre suivant.

  1. Écrivez un programme en langage assembleur qui commence à 0200 $ pour le 6502 µP et ajoute les nombres non signés de 2A94 H (ajouter) à 2ABF H (augend). Laissez les entrées et les sorties être dans la mémoire. Produisez également à la main le document de programme assemblé.
  2. Écrivez un programme en langage assembleur qui commence à 0200 $ pour le 6502 µP et soustrait les nombres non signés de 1569 H (soustraire) de 2ABF H (fin de minute). Laissez les entrées et sorties être dans la mémoire. Produisez également à la main le document de programme assemblé.
  3. Écrivez un programme en langage assembleur pour le 6502 µP qui compte de 00 $ à 09 $ à l'aide d'une boucle. Le programme devrait commencer à 0200 $. Produisez également à la main le document de programme assemblé.
  4. Écrivez un programme en langage assembleur qui commence à 0200 $ pour le 6502 µP. Le programme comporte deux sous-programmes. Le premier sous-programme ajoute les nombres non signés de 0203 H (augend) et 0102H (addend). Le deuxième sous-programme additionne la somme du premier sous-programme qui est 0305H à 0006 H (augend). Le résultat final est stocké dans la mémoire. Appelez le premier sous-programme qui est FSTSUB et le deuxième sous-programme qui est SECSUB. Laissez les entrées et sorties être dans la mémoire. Produisez également à la main le document de programme assemblé pour l’ensemble du programme.
  5. Étant donné qu'un IRQ le gestionnaire ajoute 02 $ à 01 $ à l'accumulateur comme gestion de base pendant que INM est émis et le traitement de base pour INM ajoute 05 $ à 04 $ à l'accumulateur, écrivez un langage assembleur pour les deux gestionnaires, y compris leurs appels. L'appel au IRQ le gestionnaire doit être à l’adresse $0200. Le IRQ Le gestionnaire doit commencer à l’adresse 0300 $. Le INM Le gestionnaire doit commencer à l’adresse 0400 $. Le résultat du IRQ le gestionnaire doit être mis à l’adresse $0500, et le résultat du INM Le gestionnaire doit être placé à l’adresse $0501.
  6. Expliquez brièvement comment l'instruction BRK est utilisée pour produire l'interruption logicielle dans un ordinateur 65C02.
  7. Produisez un tableau qui compare et met en contraste un sous-programme normal avec une routine de service d'interruption.
  8. Expliquez brièvement les principaux modes d'adressage du 65C02 µP à partir des exemples d'instructions en langage assembleur.
  9. a) Écrivez un programme en langage machine 6502 pour mettre le « Je t'aime ! » chaîne de codes ASCII en mémoire, en commençant par l'adresse $0300 avec la longueur de la chaîne. Le programme devrait démarrer à l'adresse $0200. Obtenez chaque caractère de l'accumulateur un par un, en supposant qu'ils y sont envoyés, par un sous-programme. Assemblez également le programme à la main. (Si vous avez besoin de connaître les codes ASCII pour 'Je t'aime!'. Les voici : 'Je' :49 16 , espace : 20 16 , 'l' : 6C 16 , 'o':6F 16 , 'dans':76 16 , 'e':65, 'y':79 16 , 'dans':75 16 , et '!':21 16 (Remarque : chaque code occupe 1 octet).
    b) Écrivez un programme en langage machine 6502 pour mettre le « Je t'aime ! » chaîne de codes ASCII en mémoire, commençant à l'adresse $0300 sans la longueur de la chaîne mais se terminant par 00 16 . Le programme devrait démarrer à l'adresse $0200. Obtenez chaque caractère de l'accumulateur, en supposant qu'ils y sont envoyés, un par un, par un sous-programme. Assemblez également le programme à la main.