Les structures de programmation sur HP-15C

Jean-Pierre Bucciol

8 mars 2024

Cet article explique les principales structures de programmation d'une calculette HP-15C. On y montre quelques équivalents en Python, histoire de donner quelques repères à ceux qui n'ont jamais eu besoin de s'habituer à ce genre de logique.

Les instructions de branchement GTO et LBL

« Dans le temps, mon jeune ami, on n'avait que ça ! »
Quand le pointeur d'un programme lit l'instruction GTO 0, il se rend directement à l'instruction f LBL 0 qu'il cherche dans la suite du code, quitte au besoin à poursuivre la recherche en reprenant à partir du début, sans exécuter les instructions entre les deux. Le GTO est évidemment l'abréviation de « go to » (« aller à ») et LBL de « label » (« étiquette »). Le langage permet 25 étiquettes : 0 à 9, .0 à .9 et A, B, C, D et E.

Ces instructions sont les briques de base de la programmation sur HP-15C. Elles ont aujourd'hui complètement disparu des langages modernes de programmation. Nos machines sont aujourd'hui tellement gorgées de mémoire et de vitesse qu'elles peuvent se permettre de nous montrer des comportements plus subtils. (J'ai écrit « montrer » parce qu'il ne faut pas se leurrer : plus on se rapproche des processeurs, plus il y a de chance que les langages de programmation utilisent des GTO.)

Et ne nous plaignons pas : dans ce langage, il y a au moins des étiquettes !

« Parce que j'ai connu un temps, mon jeune ami, où chaque ligne était obligatoirement numérotée et où les seuls branchements possibles étaient à un numéro de ligne : toute suppression de ligne avant la ligne cible du branchement demandait à modifier aussi le branchement... »

Les instructions conditionnelles

Les instructions conditionnelles font partie des briques standards de tout langage de programmation. Ils permettent des branchements qui sont effectués, ou pas, selon qu'une condition est vraie ou fausse. Sur une calculette HP-15C, les tests des conditions ne peuvent être faits que sur le contenu du premier registre (X) ou des deux premiers registres (X et Y) de la pile opérationnelle, donc évidemment uniquement sur des nombres. Et les seuls tests possibles sont des comparaisons. Le premier registre de la pile peut être comparé à 0. Les deux premiers registres de la pile peuvent être comparés entre eux. Deux instructions conditionnelles sont accessibles directement par une touche clavier : g x=0 et g x≤y. Dix autres sont disponibles via un numéro et la commande préfixe g TEST :

au clavier
x=0 g x=0
x≤y g x≤y
x≠0 g TEST 0
x>0 g TEST 1
x<0 g TEST 2
x≥0 g TEST 3
x≤0 g TEST 4
x=y g TEST 5
x≠y g TEST 6
x>y g TEST 7
x<y g TEST 8
x≥y g TEST 9

(Un tableau récapitulatif semblable se trouve au dos de la calculatrice : ouf !)

Comment utiliser ces instructions ? Le cas le plus simple d'instructions conditionnelles est le SI/SINON. En Python :

if [condition] :
    [bloc 1]
else :
    [bloc 2]
[bloc 3]

Cela peut se traduire pour HP-15C par :

[condition]
GTO 1
[bloc 2]
GTO 2
f LBL 1
[bloc 1]
f LBL 2
[bloc 3]

On peut aussi nier la condition (symbole ! précédent la condition dans ce qui suit) et obtenir la variante :

[!condition]
GTO 1
[bloc 1]
GTO 2
f LBL 1
[bloc 2]
f LBL 2
[bloc 3]

On peut encore déporter l'un des blocs 1 ou 2 ailleurs dans le programme :

[condition]
GTO 1
[bloc 2]
f LBL 2
[bloc 3]
Puis, ailleurs :

f LBL 1
[bloc 1]
GTO 2
Remarque : on suppose implicitement ici que le bloc 3 finit proprement par un g RTN.

Exemple d'utilisation :

En Python :

if n%2 :
    n=n/2
else :
    n=3*n+1
On suppose que le nombre n ci-dessus se trouve dans le premier registre (X) de la pile opérationnelle de la HP-15C. Alors :

ENTER
ENTER
2
÷
f FRAC
g x=0
GTO 1
x↔y
3
×
1
+
GTO 2
f LBL 1
x↔y
2
÷
f LBL 2

En Python, on utilise la fonction % (reste de la division euclidienne) pour tester si le nombre est pair. Cette fonction n'existe pas sur HP-15C, on teste donc ici la partie décimale (f FRAC) du quotient de la division par 2. L'exemple est tiré de mon article consacré à la suite de Syracuse sur une HP-15C.

Venons en à un branchement conditionnel sans SINON en Python :

if [condition] :
    [bloc 1]
[bloc 2]
Il peut facilement être traduit par :

[!condition]
GTO 1
[bloc 1]
f LBL 1
[bloc 2]

Les boucles non bornées

Il n'existe pas d'instructions spécifiques pour faire des boucles sur HP-15C. On fait tout avec les instructions de branchement et les instructions conditionnelles. Voici un simple while en Python :

while [condition] :
    [bloc 1]
[bloc 2]

Sur HP-15C, sans instruction spécifique, il faut effectuer un branchement conditionnel sur une étiquette que l'on a placée juste avant le test de la condition :

f LBL 1
[!condition]
GTO 2
[bloc 1]
GTO 1
f LBL 1
[bloc 2]

Les boucles bornées

En Python :

for i in range(1,n+1) :
    [bloc 1]
[bloc 2]

Ce type de boucle n'est qu'un cas particulier du précédent, puisqu'il est totalement équivalent à :

i=1
while i<=n :
    [bloc 1]
    i=i+1
[bloc 2]

L'implantation pour HP-15C est donc identique à la précédente :

STO 0
1
STO I
f LBL 1
RCL 0
RCL I
g TEST 7
GTO 2
[bloc 1]
1
STO + I
GTO 1
f LBL 2
[bloc 2]
Explications :

Il est possible de se passer du registre Rₒ si les opérations faites dans le bloc 1 ne sont pas trop complexes et n'éliminent pas la valeur de n de la pile opérationnelle.

Un exemple typique mathématique est le calcul du rang minimal dans une suite pour passer un seuil. Voir mon article consacré aux suites sur une HP-15C.

Contrôle de boucle via le registre Index

La HP-15C propose aussi une implémentation particulière permettant de contrôler, quelques fois plus simplement mais pas toujours, les boucles : le « contrôle de boucle via un registre ». La partie entière et la partie décimale d'un registre, peuvent, associées à certaines instructions, jouer des rôles particuliers. N'importe quel registre peut être utilisé pour cela, mais on ne parlera dans la suite que du registre Index R_I. S'il s'appelle ainsi, c'est qu'il y a une raison.

Associées à certaines instructions, la partie entière du registre peut jouer le rôle d'un compteur; les trois premiers chiffres de la partie décimale peuvent jouer le rôle d'une valeur de test; et les deux chiffres suivants de la partie décimale peuvent jouer le rôle de valeur d’incrément ou de décrément.

Autrement dit, si le registre R_I contient le nombre décimal nnnnn,xxxyy :

Les instructions f ISG I et f DSE I permettent alors d'effectuer des branchements conditionnels utilisant les particularités de ce registre. L'instruction f ISG I, tout à la fois :

L'instruction f DSE I est semblable, mais elle décrémente le compteur nnnnn et effectue le test de la condition nnnnn ≤ xxx;

Quelques remarques :

À quoi cela peut-il servir, me direz-vous ? Et bien à faire (un peu) plus vite une suite d'opérations courantes de gestion d'une boucle, à désencombrer la pile opérationnelle et à utiliser moins de registres. Pourquoi pas ? Par exemple, le code Python précédent :

for i in range(1,n+1) :
    [bloc 1]
[bloc 2]

peut aussi être traduit par :

1
0
0
0
÷
STO I
f LBL 1
f ISG I
GTO 2
[bloc 2]
f LBL 2
[bloc 1]
GTO 1

Explications :

Remarque : on suppose encore implicitement que le bloc 2 se termine proprement par un g RTN.

Un exemple typique d'utilisation mathématique est le calcul du n-ième terme d'une suite. Voir mon article consacré aux suites sur une HP-15C.

Les sous-programmes

Après l'ésotérique, on retombe dans l'ordinaire : les sous-programmes.

« Et encore, mon jeune ami, tout au début, y'avait même pas ça : on y allait à la truelle GTO ! »
L'instruction GSB 0 est semblable à GTO 0 et permet de se rendre directement à l'instruction f LBL 0. La différence est qu'elle s'attend ensuite à rencontrer une instruction g RTN. Une fois arrivée à cette dernière, le programme revient à l'instruction qui suit l'appel GSB 0. GSB est évidemment pour « go to subroutine » (« aller au sous-programme »), RTN pour « return » (« retour »). Le sous-programme étiqueté par f LBL 0 peut être lancé indépendamment directement au clavier avec la commande GSB 0.

En Python :

def mafonction():
    [bloc 1]
[bloc 2]
mafonction()
[bloc 3]
mafonction()
[bloc 4]

Sur HP-15C :

f LBL 0
[bloc 1]
g RTN
[bloc 2]
GSB 0
[bloc 3]
GSB 0
[bloc 4]

L'utilité d'un sous-programme est la même que dans un langage moderne : il permet d'exécuter autant de fois que l'on veut un bloc d'instructions, sans avoir à le réécrire. Dans un langage moderne, la deuxième utilité des sous programmes (qui a dit la première ?) est de compartimenter le code pour le clarifier, mais étant données l'implémentation et l'interface très... particulières de la HP-15C, c'est ici juste mentionné pour rigoler !

← Article précédent
Systèmes linéaires et matrices sur HP-15C, mars 2024
Article suivant →
Nombres premiers sur HP-15C, mars 2024

Je préfère vraiment les contacts à l'ancienne, par courrier électronique à l’adresse jpsmail(at)free.fr. Antispam : penseras-tu à remplacer (at) par @ dans l’adresse ? Que cela ne t'enpêche pas d'ajouter un commentaire :

Nom :

Commentaire :

Articles (304)

   (*: nécessite un mot de passe.)
↑ Retour en haut de la page