Adloun

Problème — Un ordinateur à programme enregistré, en Python

Exercice de TD · niveau 3 (difficile) · NSI (terminale), chapitre 15 — Histoire de l'informatique

Énoncé

Problème — Un ordinateur à programme enregistré, en Python.

On reconstitue une machine minimale conforme au rapport de 1945. Sa mémoire est une liste de entiers ; les instructions y sont rangées comme les données. Une instruction est un entier de la forme , avec le jeu d'instructions suivant, où acc désigne l'accumulateur et co le compteur ordinal :

CodeNomEffet
0STOParrêter la machine
1CHARGE a`acc` `memoire[a]`
2RANGE a`memoire[a]` `acc`
3AJOUTE a`acc` `acc + memoire[a]`
4SOUSTRAIT a`acc` `acc - memoire[a]`
5SAUTE a`co` `a`
6SAUTE_SI_POSITIF asi `acc > 0`, alors `co` `a`

Corrigé

1. La machine. Le cycle tient en une dizaine de lignes : c'est exactement le schéma de l'architecture à programme enregistré.


def executer(memoire):
    acc = 0          # accumulateur
    co = 0           # compteur ordinal
    while True:
        instruction = memoire[co]
        code = instruction // 100
        adresse = instruction % 100
        co = co + 1                      # on avance AVANT d'executer
        if code == 0:
            return memoire
        elif code == 1:
            acc = memoire[adresse]
        elif code == 2:
            memoire[adresse] = acc
        elif code == 3:
            acc = acc + memoire[adresse]
        elif code == 4:
            acc = acc - memoire[adresse]
        elif code == 5:
            co = adresse
        elif code == 6:
            if acc > 0:
                co = adresse

Le programme s'écrit directement en nombres, puisque c'est ainsi qu'il est rangé :


memoire = [0] * 100
memoire[0] = 121   # CHARGE 21          acc <- somme
memoire[1] = 320   # AJOUTE 20          acc <- somme + n
memoire[2] = 221   # RANGE 21           somme <- acc
memoire[3] = 120   # CHARGE 20          acc <- n
memoire[4] = 422   # SOUSTRAIT 22       acc <- n - 1
memoire[5] = 220   # RANGE 20           n <- acc
memoire[6] = 600   # SAUTE_SI_POSITIF 0 si n > 0, on recommence
memoire[7] = 0     # STOP
memoire[20] = 5    # n
memoire[21] = 0    # somme
memoire[22] = 1    # la constante 1

executer(memoire)
print(memoire[21])   # affiche 15

2. Déroulé. En co = 0, l'instruction vaut : code , adresse , donc acc memoire[21] . En co = 1, l'instruction donne acc . En co = 2, l'instruction range dans la case . Les instructions à décrémentent le compteur rangé en case , et l'instruction renvoie l'exécution en tant qu'il reste positif.

3. Résultat. La case contient successivement , , , , puis : c'est bien , la case valant alors .

4. Un programme qui se modifie lui-même. Puisque les instructions sont des nombres rangés en mémoire, rien n'interdit de les manipuler :


memoire[30] = 1
# CHARGE 0 ; AJOUTE 30 ; RANGE 0
# l'instruction 121 (CHARGE 21) devient 122 (CHARGE 22)

Cette possibilité découle directement du choix de 1945 : une seule mémoire pour les instructions et les données. C'est elle qui rend possibles les compilateurs, les interpréteurs et les systèmes d'exploitation — un programme qui en fabrique ou en lance un autre. Très employée dans les années 1950 faute de mémoire, on l'évite aujourd'hui : un programme qui se réécrit est illisible, impossible à tester, et c'est le mécanisme même de nombreuses attaques informatiques — les systèmes modernes marquent d'ailleurs les zones de code comme non modifiables. La leçon est générale : la puissance d'un mécanisme et sa dangerosité ont souvent la même origine.

Les autres exercices de ce chapitre Le cours du chapitre

Un blocage sur cet exercice ? Le tuteur d'Adloun guide par questions, sans donner la réponse.