Présentation du projet
L’article propose un tutoriel littéraire qui construit une machine virtuelle LC‑3 en environ 250 lignes de code C. Le guide couvre la définition des registres, la gestion de la mémoire, le décodage des opcodes, les traps, le chargement de programmes et les entrées spécifiques à la plateforme. Le choix de la LC‑3, architecture 16‑bits à 16 opcodes, vise à rendre les mécanismes d’exécution du processeur et le langage bas‑niveau accessibles aux développeurs.
Architecture et implémentation
La VM repose sur un tableau de 65 536 mots de 16 bits pour la mémoire principale, reflétant l’espace d’adressage complet de la LC‑3. Les huit registres généraux (R0‑R7) sont stockés dans un tableau uint16_t reg[8]. Le cycle d’instruction suit le modèle fetch‑decode‑execute : le compteur de programme (PC) lit l’opcode, le décodage utilise un switch sur les 4 bits supérieurs, et chaque cas implémente l’opération correspondante (ADD, AND, LD, ST, etc.). Le code source inclut également la prise en charge des traps, qui invoquent des fonctions d’entrée/sortie via printf et scanf pour les interactions console.
uint16_t fetch() {
uint16_t instr = mem[pc++];
return instr;
}
void decode_execute(uint16_t instr) {
uint16_t opcode = instr >> 12;
switch(opcode) {
case 0x1: // ADD
// implémentation ADD
break;
case 0x2: // LD
// implémentation LD
break;
// ... autres opcodes ...
}
}
Analyse des choix techniques
Le recours à une architecture à 16 opcodes simplifie le décodage binaire et limite la taille du switch, ce qui réduit le nombre de lignes de code nécessaires. L’utilisation de types uint16_t garantit la conformité avec la largeur de mot de la LC‑3 et évite les dépassements de capacité. Le modèle de mémoire linéaire évite la complexité de la pagination, mais impose une allocation complète de 128 KB, ce qui reste raisonnable pour un environnement d’apprentissage. Le tutoriel montre comment les traps sont mappés à des appels système standards, illustrant la transition entre le modèle virtuel et les API d’entrée/sortie du système hôte.
Limites et perspectives
La VM ne gère pas les extensions matérielles telles que les interruptions ou le mode protégé, ce qui limite son usage aux programmes d’exemple fournis dans les cours d’architecture. L’absence de gestion dynamique de la mémoire empêche l’expérimentation avec des stratégies d’allocation avancées. Pour des projets plus ambitieux, il serait possible d’ajouter un simulateur de pipeline, d’intégrer un débogueur interactif ou de porter le code sur des plateformes embarquées en remplaçant les appels printf/scanf par des interfaces UART.