Débuter en assembleur

Si vous voulez imprimer, prenez cette version

Généralités sur l'hexadécimal
L'assembleur
Les registres
Le premier programme
Les sauts
Le processeur
Les pointeurs

Généralités sur l'hexadécimal

L'hexadécimal est le système de numérotation en base 16, comme le décimal est le système de numérotation en base 10. On notera pour la suite #123 d pour 123 en base 10, #123 h pour 123 en base 16 et #1101 b pour 1011 en base 2 (système binaire). En base 10 il y a 10 chiffres : 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. Et en base 16 il y a 16 chiffres 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E.

Conversion base x -> base 10.

C'est idiot à dire mais pour savoir à quoi est égal 123, il faut faire 123=1*100+2*10+3*1=1*10²+2*101+3*100=123. A quoi est égal #1AB h ? On refait pareil : #1AB=1*16²+A*16+B*16=1*256+10*16+11*1=#427 d. Pour le binaire on a que 2 chiffres : 0 et 1. #1011 b=1*2^3+0*2^2+1*2^1+1*2^0=8+0+2+1=#11 d

Conversion base 10 -> base x

Comment transformer #123 d en base 16 ? .

Il suffit de décomposer 123 en x*16^1+y*16^0=16x+y. On a 123/16=7.6875,en arrondissant par défaut on a x=7, d'où 123=16*7+y. y=11, soit B. Conclusion : #123 d=#7B h.

Mais enfin, pourquoi est - ce que je vous fais faire ça ?

Base 16 -> base 2 & base 2 -> base 16

Un dernier petit exercice : transformer #ABC h en binaire. Il y a une astuce : 2^4=16, donc 4 chiffres en binaire font 1 chiffre en hexadécimal. On transforme A en binaire : #A h=10=1*8+1*2=#1010 b, B en binaire: #B h=1011 b et #C h=1100 b. D'où #ABC h=# 1010 1011 1100 b. Un exercice dans l'autre sens : # 0110 1000 1001 b, le premier chiffre : 4+2=6, les autres sont 8 et 9 ; # 0110 1000 1001 b=# 689 h

Tout ceci pour vous dire que l'hexadécimal est un système qui simplifie la vie.
Lequel est le plus facile à lire : #0110 1000 1001 b ou # 689 h ?

Et un processeur ne comprends que le binaire, 0 si pas de tension et 1 s'il y a une tension dans un fil.

On a donc inventé l'hexadécimal pour que l'homme puisse donner des instructions au processeur facilement.
Et oui, vos programmes ne ressemblent qu'a ceci : "D9D20E1632C2A20F10000554459445023455259454558593632B2130". Je sais, pourtant, vous tapez << DUP >>, et pas D9D20E163078BF193632B2130. En fait, quand vous tapez << DUP >>, il y a un programme, qui fait : je trouve <<, je remplace par D9D20E1630, je trouve DUP, je mets 78BF1, je trouve >>, je mets 93632B2130. Ce programme c'est un compilateur.

L'assembleur

Le compilateur transforme une suite de mnémotechniques en langage machine. Dans notre cas, le langage de programmation (ou la suite de mnémotechniques) est l'assembleur. Ex :
"A=DAT0 A
D0=D0 +5
PC=(A)
@"
Voici un programme en assembleur. Chaque instruction est sur 1 seule ligne et le programme se finit par un @ ( fait sur HP avec la combinaison de touches [alpha] [->] [ENTER] ), suivi immédiatement par la fin du texte. Pour transformer ce texte en langage machine, il faut le compilateur, qui s'appelle lui aussi assembleur (Si vous le voulez, alors allez à ma page sur le téléchargement). La compilation s'appelle assemblage, prendre le langage machine et le transformer en assembleur c'est désassembler, il faut un désassembleur.

L'assembleur est, comme partout, le langage le plus rapide. Chaque instruction corresponds à une instruction directement exécutable par le processeur, c'est pourquoi ce langage est très dépendant du processeur.

Les registres de calcul

Dans la HP48, le processeur s'appelle le SATURN (le joli nom !). Il possède 4 registres de calcul. Il y a aussi les registres de sauvegarde,et puis PC & Compagnie, mais on les verra plus tard.

Qu'est-ce qu'un registre ?

Un registre est une "case mémoire" située à l'intérieur du processeur. Les registres de calcul sont "A, B, C et D". On peut y stocker une valeur avec un LC ou avec un LA, LC veut dire Load C et LA, Load A. Et oui LB et LD n'existent pas, on ne peut charger les valeur que dans "C" ou "A" Concrètement, dans le programme on met LC 12D21, et on va charger 12D21 dans C. De même on peut faire des additions entre registres. Exemple : C=A+B W ou A=A+C X. Vous devez surement vous demander ce que le W et le B viennent faire là.

Les Champs

Les registres de calcul et de sauvegarde (je détaillerais ceux de sauvegarde un peu plus loin) ont une taille de 16 quartets. Un quartet est la taille d'un chiffre en hexadécimal. 1 quartet=4 bits, et comme 1 octet = 8 bits, 1octet = 2 quartets. On a le tableau suivant :

Quartet n° 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Champs W
S M XS B
  A
  X
<-- P -->
  WP

Remarque : Le premier quartet est le quartet 0, le 2eme est le quartet 1... le 16eme quartet est le quartet 15.

Un champ est utilisé pour designer une partie des registres
Quand on fait C=A+B X, on additionne A et B sur le champ X. Soit ,au départ, le cas suivant :

Quartet n° 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
A 1 2 3 4 A E 1 2 5 B 0 B 1 4 D 9
B 2 4 6 8 B F 2 4 A C 3 A 1 5 C 2
C 1 8 1 4 1 8 9 8 1 C 3 2 E D 2 0

L' addition ne se fait que sur le champ X (quartets en gras), C deviendra:

Quartet n° 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
C 1 8 1 4 1 8 9 8 1 C 3 2 E A 9 B

Les 3 premiers quartets ont été les seul à changer de valeur. A partir de maintenant, on notera Cx pour le champ x de C. Plus généralement on notera Xy le champ y du registre X (c'est un exemple, n'allez pas chercher Y dans le tableau !)
Ca suffit! On va faire le premier programme.

Le premier programme

Voici votre premier programme :

"            %%% Remarquez que les commentaires sont précedés de "%"
LC 186A0     %%% La valeur est en hexa, je vous donne la conversion
             %%% #186A0 h = #100000 d
*BOUCLE      %%% On vient de faire un label
C=C-1 A      %%% On décrémente Ca de 1. Attention de ne pas confondre
             %%% le registre A avec le champ A
?C#0 A       %%% On a un test, le # veut dire différent
GOYES BOUCLE %%% Apres le test, un renvoi conditionnel
             %%% Si le test est satisfait, alors le saut est executé
             %%% Sinon, le programme continue à l'instruction
             %%% apres le saut, c'est à dire maintenant
A=DAT0 A     %%% \
D0=D0 +5     %%% |-> La séquence de retour au RPL
PC=(A)       %%% /   Je l'expliquerait plus tard
@"

En résumé le programme charge 100 000 dans C, puis luis soustrait 1, jusqu'à ce que C=0. Le programme soustrait 100 000 fois 1 à C.
Le programme nous montre :

Compilez le programme, executez le : il met environ 1 seconde! Je propose de faire le même en RPL, mais avec seulement 1000 pour comparer.
<< 1000 WHILE 1 - DUP REPEAT END >>
Ce programme met 5 sec. Le language machine a été 500 fois plus rapide. Rassurez-vous, il n'est souvent que 200 fois plus rapide.

On peut comparer comme ça :
RPL Assembleur

Les sauts

Un saut peut avoir plusieures caractéristiques :

On peut résumer la majoritée des sauts avec le tableau suivant :

Référence relative absolue
Saut court long court & long
Sans retour GOTO GOLONG GOVLNG
Avec retour GOSUB GOSUBL GOSBVL
Avec test GOYES
Avec test sur la carry GONC & GOC

Je ne m'étendrais pas plus sur le GOTO.

GOSUB & GOSUBL

Les sauts avec retours font comme des procedures en Pascal ou comme les fonctions de type void en C/C++. Elles font sauter le programme au label spécifié puis avec un RTN le programme revient la ou le saut a été appellé. Exemple :

"%%% Ce programme est equivalent au premier programme
LC 186A0
*BOUCLE
GOSUB DECREMENTE_C  %%% On appelle la sorte de sous fonction
?C#0 A              %%%  <-----------------------------------------\
GOYES BOUCLE        %%%                                            |
GOVLNG 12002        %%% Ce saut renvoie à l'addresse 12002         |
                    %%% où il y a A=DAT0 A   D0=D0+5   PC=(A)      |
*DECREMENTE_C       %%% Voici la sorte de sous-routine             |
C=C-1 A             %%%                                        _   |
RTN                 %%% Le RTN marque la fin de la sous-routine |__/
                    %%% On revient là ou le label a été appellé_|
@"

Sauts courts contre sauts longs

Le saut devient long quand if faut faire un saut de plus de 1024 octets. Si l'on met un GOTO alors que le saut fait plus de 1024 octets, l'assembleur renverra le message d'erreur "Jump too long". Pourquoi ne pas mettre des sauts long à tue-tête? Parce que les sauts long prennent plus de place et sont plus lents que les sauts courts. Il n'y a malheuresement qu'un seul saut qui s'execute avec un test, c'est le GOYES, et ce saut est court. si l'on doit faire un test puis un saut de plus de 128, il faut commencer a bricoler. Par exemple au lieu de mettre le code 1, il faudrait mettre le code 2.

Code 1 Code 2
"......
*LABEL_1
......
?C=0 A
GOYES LABEL_1
......
@"
"......
*LABEL_1
......
?C#0 A
GOYES PETIT_SAUT
GOLONG LABEL_1
*PETIT_SAUT
......
@"

La carry & les débordements

Il y a aussi un saut qui fait un test sur la carry. La carry c'est un drapeau, c'est a dire qu'elle est toujours à 0 (désarmée) ou à 1 (armée). GOC (GO if Carry) s'effectue quand la carry est armée et GONC (GO if No Carry) quand la carry est désarmée. La carry s'arme apres chaque saut satisfait avec un test. Exemple :

"LC 00001
?C#0 A
GOYES TEST_BON  %%% Comme on vient de faire un LC 1, le test sera vrai
*TEST_BON       %%% on va faire le saut
GOC FIN         %%% la carry est armée, sinon
*BCL            %%% on boucle à l'infini
GOTO BCL        %%% Remarque: pour arreter un programme qui 
                %%% boucle à l'infini, if faut faire [ON][C]
*FIN
GOVLNG 12002    %%% Ce saut renvoie à l'addresse 12002
                %%% où il y a A=DAT0 A   D0=D0+5   PC=(A)
@"

Donc si ce que j'ai dit est vrai le programme ne fait rien, sinon il bloque la HP48. Essayez sans crainte.

Mais la carry s'arme aussi quand on a un débordement. Comme d'habitute l'exemple vaut mieux que les mots

Quartet n° ... et les
11 autres
quartets
4 3 2 1 0
Registre A A 2 5 E 0
Registre B 8 3 7 D 8

On fait C=A+B A. Normalement #A25E0 h + # 837D8 h = # 125DB8 h. Et oui, on est content mais le champ A ne modifie que les 5 premiers quartets de C or la somme ne peut s'ecrire que sur 6 quartets, on a un débordement. Le processeur decide de tronquer le chiffre en trop, on a alors :

Quartet n° 4 3 2 1 0
Champ C 2 5 D B 8

Et le SATURN nous signale le déborement en armant la carry. Autre exemple: C=A-B A.Si Aa > Ba, pas de probleme, le nombre est positif, mais si Aa < Ba, alors Aa-Ba est négatif.

Quartet n° ... et les
11 autres
quartets
4 3 2 1 0
Registre A 8 3 7 D 8
Registre B A 2 5 E 0
A-B : Registre C E 1 1 F 8

Et pourtant il y a un resultat.On a Aa-Ba= -(Ba-Aa). Or Ba-Aa= #1EE08 h. Pour faire l'opposé de #100111 b, on fait l'opposé de chaque bit, d'où - #100111b= #011000 b. Et -#1EE08 h = #E11F8. Autre methode : Aa-Ba=Aa+(-Ba). Comme -Ba= - # A25E0 h = # 5DA20 Et # 837D8 h(Aa) + # 5DA20 h(-Ba) = # E11F8. L'intéret de faire ceci c'est de se rendre compte que #0-#1=#FFFFF h sur le champ A. Très pratique ce 0-1 qui entrainne la carry. Le premier programme peut se réécrire sous la forme :

"LC 186A0
*BOUCLE
C=C-1 A
GONC BOUCLE
GOVLNG 12002 %%% Pour sortir
@"

Mais attention, car le premier programme bouclais 100 000 fois, et celui-ci boucle 100 001 fois. Le programme avec le GONC ne s'arrete pas à 0, mais juste après.

GOSBVL & GOVLNG

Le GOSBVL et le GOVLNG prennent tous 2 des addresses et non pas des labels. Ils font un saut à l'addresse donnée, qui est toujours en ROM (on peut faire le saut en RAM, mais je vois pas l'interet, à part peut être pour le Meta-Kernel). En fait on va chercher en ROM un morceau de programme, qui va faire un fonction complexe,ou longue, mais qu'on a pas envie de se faire chier à retaper, voir recréer. Exemples : Le GOVLNG 12002 qui permet de retourner au RPL, le GOVLNG 05023 qui renvoie une erreure, le GOSBVL 65807 qui fait la division de Aw par Cw et qui stocke le résultat dans Aw et Cw, le reste dans Bw, le GOSBVL 53EE4 qui fait (Aw et Cw)=Aw*Cw, mais Dw est utilisé. La différence entre le GOSBVL et le GOVLNG, c'est que le GOSBVL fait ça routine et revient à notre programme, alors que le GOVLNG ne revient plus à notre programme. Le GOSBVL 05023, on peut l'appeler en plein milieu du programme, comme une sorte de fonction, alors que le GOVLNG 12002 ne redonne plus la main à notre programme, il donne la main au système de la HP.

Le processeur

Le processeur possède :

4 registres de calcul : A, B, C et D

Les liens entre les registres de calculOn peut les additionner entre eux, ou les soustraire, mais pour les multilpier ou diviser il faut un GOSBVL, car ces opérations ne sont pas directement accessibles par le processeur. On est en assembleur, donc n'essayez pas de faire des trucs dans le genre C=C-A-B+D W. Il y a aussi l'instruction toute bête qui constste à copier les valeurs d'un registre à un autre. Ex : C=A A. Mais on peut aussi, au lieu de copier, d'échanger les valeurs. Ex: CAEX A (EX pour EXchange): Ba prends la valeur de Aa, et Aa prends la valeur de Ba. Chaque registre ne peut faire des opérations qu'avec le registre adjacent, sauf le C, qui sait tout faire. On peut aussi faire des décalages de bits : Les exemples sont pris sur le champ W de C, mais les instructions marchent sur tout les registres de calcul et sur tout les champs.

Direction du décalage Gauche Droite Notes
Quantitée décalée
1 bit C=C+C W CSRB W
(Schift Left Bit)
Décaler d'un bit vers la gauche revient a multiplier par 2,
et vers la droite a diviser par 2
1 quartet CSL W
(Schift Left)
CSR W
(Schift Right)
Décaler d'un quartet vers la gauche / droite
revient a multiplier / diviser par 16

Décaler c'est beau, mais on pert un bit / quartet à chaque fois (Ex: 1 bit vers la gauche : #1001101b-->#0100110b) et si on veut on peut faire une rotation (Ex 1 bit vers la gauche : #1001101b-->#10100110b). L'instruction est : CSLC (Shift Left Circular) et CSRC (Schift Right Circular). Ca marche sur tout les registres (de calcul), mais que sur le champ W.

Il existe aussi des instructions pour modifier les registres bit à bit. On rappelle que les registres font 64 bits, le premier est le 0 et le dernier le 63. Pour mettre à 0 le bit 7 de C, l'instruction est CBIT=0 7. Pour mettre à 1 le bit 15 de A : ABIT=1 15. Ces instructions marchent sur tout les registres, mais seulement sur les bits 0 à 15. Il y a aussi l'instruction pour le test. Si le bit 15 de C est à 1, alors va au label SAUT_1 s'écrit :

".....
?CBIT=1 15
GOYES SAUT_1
.....
@"

Ne cherchez pas a faire "?CBIT#1 12", car cela revient à "?CBIT=0 12", ou vous aurez une erreur de compilation.

Important : On peut faire des LC 12345 , mais aussi des LC AB , ou des LC 12000000003,
mais un LC 1 est totalement différent d'un LC 00001
Quand on fait un LC 1, il n'y a que le quarte 0 de C qui change, alors que quand on fait un LC 00001, les quartets 0 à 4 de C changent. L'exemple : On suppose que Cw=00123456789ABCDE
avec un LC 1, Cw=00123456789ABCD1
avec un LC 00001, Cw=0012345678900001
Donc si l'on veut initialiser Ca à 1, il faut faire LC 00001
Si l'on veut initilaiser Cw à 1, on peut faire LC 0000000000000001 (mais le mieux c'est de faire C=0 W et LC 1)

5 registres de sauvegarde R0, R1, R2, R3, R4.

Ces registres sont identiques à ceux de caluculs, sauf que l'on ne peut pas y faire de calculs (ah, ah, ah...). On ne peut que faire des "copies" ou des échanges de valeurs entre eux et les registres de calcul. Exemple : R0=C A : stocke la valeur de Ca dans R0a. A=R3 W : stocke la valeur de R3w dans Aw. BR2EX X : échange la valeur de R2x avec Bx. Ne pas faire R0=R3 W (On peut remplacer par : AR0EX W R3=A W AR0EX W), ni C=R0+A W.

Les drapeaux ST

Un drapeau est soit à 0, soit à 1. Les drapeaux ST sont 16: du 0 au 15, mais les 12, 13, 14, 15 sont utilisés par le système, donc n'y touchez pas (sauf si vous êtes un pro). On a donc 12 drapeaux a notre disposition.
Mettre à 0 : ST=0 n où n est le numéro du drapeau. Ex : ST=0 0
Mettre à 1 : ST=1 n . Ex : ST=1 0
Faire des test : ?ST=0 n ou ?ST=1 n (et pas de ?ST#0 n, c'est compris)

La pile RSTK

La pile RSTK est une pile de 8*20 bits (8 étages de 5 quartets). Elle sert au processeur pour les sauts avec retour. Quand on fait un GOSUB, par exemple, le processeur empile dans la RSTK l'addresse ou le GOSUB à été placé, puis quand il tombe sur le RTN, le processeur "dépile" la RSTK et va à l'addresse indiquée. Puisque la RSTK est limitée à 8 niveaux, on ne pourra pas encastrer plus de 8 GOSUBS. Les instructions :
RSTK=C pour mettre dans le niveau le plus bas de la pile l'addresse contenue dans C
C=RSTK pour mettre dans C la dernière addresse empilée.

Le registre P

Il permet d'acceder séparément à tout les quartets des registres.
P=n : place P sur le quartet n. Ex : P=0. Note : P est toujours compris entre 0 et 15 inclus
P=P+n & P=P-n : incrémnte/décrémente P de n. Note: ces instructions peuvent armer la carry.
P=C n : P prends la valeur du quatet n de C
C=P n : le quatet n de C prends la valeur de P
CPEX n : échange ...
?P=0 & ?P#0 : devinez ...

P n'a que un seul quartet de large, mais WP englobe les quartets, du quartet 0 au quartet désigné par P.
Important : P influence l'instruction LC et LA : la valeur chargée ne sera chargée qu'a partir du quartet désigné par P. L'exemple qui éclairci tout : On fait un LC ABCDE (On suppose que Cw est nul)
Si P=0 Cw : 00000000000ABCDE
Si P=1 Cw : 0000000000ABCDE0
Si P=3 Cw : 00000000ABCDE000
Si P=14 Cw : DE00000000000ABC

Le registre PC

Ce registre de 20 bits (5 quartets) contient l'addresse de l'instruction en cours.
On peut faire C=PC, A=PC, PC=C, PC=(A). L'exemple vaut mieux que les mots (si vous ne comprenez pas l'exemple, c'est pas grave car on se sert peu du registre PC).

"GOSBVL 0679B %%% On sauvegarde les registres
LC 186A0
B=C A         %%% On charge 100 000 dans Ba (et oui LB n'existe pas)
C=PC          %%% C contient l'addresse entre le C=PC et le A=PC
A=PC          %%% A contient l'addresse entre le A=PC et le A=C-A A
A=A-C A       %%% A est la différence des deux addresses, donc A
              %%%  contient la taille en quartets de l'instruction
              %%%  A=PC et la taille de C=PC est la même que
              %%%  celle de A=PC
C=C-A A       %%% C contient l'adresse avant le C=PC
B=B-1 A       %%% On décrémente B
GOC FIN       %%% Si B=0 avant la décrémentation, alors 0-1 arme la
PC=C          %%% carry, sinon on dit au processeur d'aller à
              %%% l'addresse que contient C, qui est l'addresse entre
              %%% le B=C A et le C=PC
*FIN
GOVLNG 05143
@"

On va boucler 100 000 fois, comme dans le premier programme. Si vous avez du mal à comprendre l'utilitée du registre PC, alors tant pis (je vais pas rajouter une page complete dessus), par contre ce qu'il faut comprendre c'est pourquoi on a mis un GOSBVL 0679B et un GOVLNG 05143 au début et à la fin du programme. On s'est servit du registre B, registre qui sert au RPL à mettre l'addresse du début de la mémoire libre, et apres avoir modifié cette valeur pour faire des calculs, il faut remettre la valeur de départ (sinion la HP apprécie pas). Le GOSBVL 0679B sauvegarde les registres D, B, D0, D1 pour apres les remettre avec un GOVLNG 05143. En résumé : des que tu touches a D, D0, D1 ou B, alors met un GOSBVL 0679B et un GOVLNG 05143

OUT & IN

Le OUT est un egistre de 12 bits, les bits 0 à 8 servent à tester le clavier et le bit 11 à manipuler le buzzer.
Le IN est un registre de 16 bits, seul les 0 à 5 et le 15 sont utilisés pou le test du clavier.
Les instructions :
OUT=C pour passer à OUT la valeur de C
C=IN & A=IN pour passer à A ou C la valeur de IN.
Mais ces instructions sont parfois bugées, c'est pourquoi on utilise toujours le GOSBVL 01160 pour C=IN et le GOSBVL 0115A pour le A=IN

INTON, SHUTDN, INT, SB, MP, SR, XM

Je ne les expliquerait pas

Les pointeurs D0 & D1

Les explications sont juste en dessous.

Les pointeurs

Sur la HP il y en a 2 : D0 et D1

Qu'est-ce qu'un pointeur ?

Un pointeur c'est un truc qui permet d'écrire en mémoire. Si je vous demande où est le 1 là dedans : 0000000000100000000, vous allez me répondre : il est après 8 chiffres en partant de la gauche. Et je peux même vous dire : Et, vas-y, met un autre 1 à 10 chifres à parir de la gauche, et vous allez me répondre 0000000010100000000. Et bien pour écrire en mémoire c'est pareil, on se sert d'un pointeur, sur la HP il y a D0 et D1. par exemple on peut dire : je met D0 à 10000 (l'addresse est en hexa, donc 65536 quartets depuis le début) et je remplace le contenu de D0 par 12345. Si toute la mémoire est remplie de zéros, et que le début est à gauche , on aura 0000000 ..(comme ça longtemps).. 00054321000 ...... j'ai souligné le quartet qui est à l'addresse # 10000 h, on peut remarquer que la valeur à été écrite à l'envers, vous verrez qu'en réfléchissant c'est tout à fait logique ...

Caractéristiques

Les addresses sont écrites sur 5 quartets.
Placer D0 à l'addresse vwxyz : D0=vwxyz
Placer D1 à l'addresse vwxyz : D1=vwxyz exemple: D0=00128 (ne mettez jamais D0=128, cette écriture peut être mal interprétée)
Le contenu de D0 est DAT0, celui de D1 est DAT1. Quelques exemples d'instruction : elles marchent avec tous les champs mais seulement les registres A et C
A=DAT0 W : met dans Aw le contenu de D0 (sur le champ W), on a fait une lecture
DAT1=C A : met dans le contenu de D1 la valeur de Ca (sur le champ A), on a écrit
DAT0=A 12 : met les 12 premier quartets de C dans le contenu de D1 (les quartets 0 à 11), on a écrit
D0=C : D0 va à l'addresse mise dans Ca
AD1EX : On échange la valeur de Aa avec l'addresse de D1 (A=D1 n'existe pas, donc on est obligé de passer par un échange)
D0=D0+n
D1=D1-n : opérations d'incrémentation/décrémentation de D1 ou D0 (pas le contenu, mais l'addresse)

Le rôle de D1

Le RPL met le pointeur D1 au niveau 1 de la pile
La pile est constituée d'une suite d'addresses de 5 quartets, ces addresses désignent les objets de la pile. Après ces addresses on a 00000. Exemple : au niveau 1 on a une chaine de caractères, qui est écrite à l'addresse # 10203 h
au niveau 2 un grob, qui est écrit en # 32153 h
au niveau 3 un programme, qui est écrit en # 12345 h
La pile est comme ceci :

00000
12345
32153
10203

L'exemple pour bien comprendre

"%% Ce programme fait un DUP
%%% On teste si il y a bien 1 niveau de pile
C=DAT1 A
?C#0 A
GOYES BON
LA 00201
GOVLNG 05023 %%% Ceci renvoie le message d'erreur 'Too Few Arguments'
*BON
D1=D1-5  %%% on recule pour avoir de la place pour
         %%% ecrire la nouvelle addresse
DAT1=C A %%% C contenait l'addresse de l'objet au niveau 1
GOVLNG 12002
@"