Généralités
sur l'hexadécimal
L'assembleur
Les registres
Le premier programme
Les sauts
Le processeur
Les pointeurs
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.
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
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 ?
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.
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.
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.
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 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.
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 :
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.
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é_| @"
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 ...... @" |
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.
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 possède :
On 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)
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.
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 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.
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
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
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
Je ne les expliquerait pas
Les explications sont juste en dessous.
Sur la HP il y en a 2 : D0 et D1
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 ...
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 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 |
"%% 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 @"