📊 Partie A - Arithmétique Avancée
A.1 - Dépassement de capacité et flags N, V, C
🧪 Exercice A.1.1 - Dépassement lors d'une addition (nombres non signés)
Q1.a) Prédictions
Résultat de 200₁₀ + 100₁₀ sur 9 bits : 300₁₀ = 100101100₂
Dans le registre A (8 bits) : 00101100₂ (on garde seulement les 8 bits de poids faible)
En hexadécimal : 2C₁₆
En décimal : 44₁₀
Q1.b) Code machine
86 C8 : ldaa #200 (C8₁₆ = 200₁₀)
8B 64 : adda #100 (64₁₆ = 100₁₀)
B7 00 20 : staa sum
Q1.c) Exécution pas à pas
| Instruction | A (hexa) | A (décimal) | Flag N | Flag V | Flag C |
|---|---|---|---|---|---|
| ldaa #200 | C8 | 200 | 1 | 0 | 0 |
| adda #100 | 2C | 44 | 0 | 0 | 1 |
Q1.d) Analyse
Le registre A contient : 2C (hexa) = 44 (décimal)
Le flag C vaut : 1
Conclusion : Le résultat est incorrect car il y a eu un dépassement. Le flag
C=1 indique qu'une retenue a été générée.
Pour obtenir le résultat correct, il faut
calculer
: C × 256 + sum = 1 × 256 + 44 = 300
🧪 Exercice A.1.2 - Dépassement avec nombres signés (flag V)
Q2.a) Test avec 127 + 1
| Instruction | A (hexa) | A (décimal signé) | N | V | C |
|---|---|---|---|---|---|
| adda #1 | 80 | -128 | 1 | 1 | 0 |
Q2.b) Interprétation
Le registre A contient : 80₁₆ = -128 (décimal signé)
Flag V = 1 : Indique un dépassement en arithmétique signée
Flag N = 1 : Indique un nombre négatif
Explication : 127 + 1 = 128, mais en complément à 2 sur 8 bits, 128 n'est pas représentable (max = 127). Le résultat "déborde" et devient -128.
Q2.c) Test avec v1=-128 et v2=-1
| Instruction | A (hexa) | A (signé) | N | V | C |
|---|---|---|---|---|---|
| adda v2 | 7F | 127 | 0 | 1 | 1 |
Q2.d) Interprétation
Le registre A contient : 7F₁₆ = 127 en décimal signé
Flag V = 1 : Indique un dépassement en arithmétique signée
Flag N = 0 : Indique un nombre positif
Explication : -128 + (-1) = -129, qui n'est pas représentable sur 8 bits signés (min = -128). Le résultat déborde et devient 127.
A.2 - Le résultat de l'opération est nul et flag Z
🧪 Exercice A.2.1 - Résultat nul et flag Z
Q3.a) Test avec v1=-1 et v2=1
| Instruction | A (hexa) | A (décimal signé) | N | Z | V | C |
|---|---|---|---|---|---|---|
| staa sum | 00 | 0 | 0 | 1 | 0 | 1 |
Q3.b) Interprétation
La case mémoire contient : 00₁₆
Flag Z = 1 : Indique que le résultat est exactement zéro
Explication : -1 + 1 = 0, le flag Z est positionné à 1 pour indiquer ce résultat nul.
- Z=1 : Le résultat est exactement zéro (très utile pour les boucles !)
- N=1 : Le bit 7 est à 1, nombre négatif en complément à 2
- V=1 : Dépassement de capacité pour opération signée (résultat < -128 ou> 127)
- C=1 : Dépassement de capacité pour opération non signée (résultat < 0 ou> 255)
A.3 - Multiplication en machine
🧪 Exercice A.3.1 - Test avec dépassement 8 bits
Q4.a) Exécution pas à pas
| Instruction | A (hexa) | B (hexa) | D (hexa) | Commentaire |
|---|---|---|---|---|
| ldaa v1 | 0A | 00 | 0A00 | A = 10₁₀ |
| ldab v2 | 0A | 28 | 0A28 | B = 40₁₀ |
| mul | 01 | 90 | 0190 | 10₁₀ × 40₁₀ = 400₁₀ |
| staa v3H | 01 | 90 | 0190 | V3H = 01₁₆ |
| stab v3L | 01 | 90 | 0190 | V3L = 90₁₆ |
Q4.b) Analyse
v3H contient : 01 (hexa)
v3L contient : 90 (hexa)
Le résultat complet v3 : v3H|v3L = 0190 (hexa)
Conversion en décimal : 0190₁₆ = 1×256 + 144 = 400₁₀
Conclusion : Oui, le résultat est correct !
Q4.c) Code source et code machine (programme exécuté)
| Code machine | Code source assembleur | ||||
|---|---|---|---|---|---|
| Address | Opcode | Operand | [Label] | operation [operand] | [comment] |
| .org $0000 | ; origine du programme en mémoire | ||||
| 0000 | B6 | 00 20 | ldaa v1 | ; [A] ← [v1] | |
| 0003 | F6 | 00 21 | ldab v2 | ; [B] ← [v2] | |
| 0006 | 3D | - | mul | ; [D] ← [A] × [B] (D = A|B sur 16 bits) | |
| 0007 | B7 | 00 22 | staa v3H | ; [v3H] ← [A] | |
| 000A | F7 | 00 23 | stab v3L | ; [v3L] ← [B] | |
| .org $0020 | ; origine des données en mémoire (variables) | ||||
| 0020 | 0A | v1 | .byte 10 | ; Premier facteur | |
| 0021 | 28 | v2 | byte 40 | ; Deuxième facteur | |
| 0022 | 01 | v3H | .byte 0 | ; Premier octet du résultat | |
| 0023 | 90 | v3L | .byte 0 | ; Deuxième octet du résultat | |
🔄 Partie B - Instructions de rupture de séquence
B.1 - Introduction aux sauts
🧪 Exercice B.1.1 - Saut inconditionnel (BRA : BRanch Always)
Q5. Exécution pas à pas
| Instruction | PC avant | PC après | A | Commentaire | |
|---|---|---|---|---|---|
| ldaa #5 | 0000 | 0002 | 05 | A = 5 | |
| bra suite | 0002 | 0006 | 05 | PC saute à l'étiquette suite ! | |
| ldaa #10 | ⚠️ Non exécutée | ||||
| suite | staa resultat | 0006 | 0009 | 05 | Suite du prog. |
Conclusion : L'instruction BRA provoque un branchement inconditionnel. Elle saute toujours, sans tester de condition.
🧪 Exercice B.1.2 - Branchement conditionnel (BEQ : Banch if EQqual to zero)
Test 1 : data = 0
Q6. Complétez le tableau
| Instruction | A | Flag Z | Branchement ? | Chemin pris |
|---|---|---|---|---|
| ldaa data | 00 | 1 | - | - |
| beq estnul | 00 | 1 | OUI | estnul |
Valeur finale dans resultat : 00
Test 2 : data = 5
Q7. Complétez le tableau
| Instruction | A | Flag Z | Branchement ? |
|---|---|---|---|
| ldaa data | 05 | 0 | - |
| beq estnul | 05 | 0 | NON |
Valeur finale dans resultat : 01
Conclusion :
- BEQ branche si et seulement si Z = 1
- Cela correspond à un résultat égal à zéro
B.2 - Premières boucles simples
🧪 Exercice B.2.1 - Compte à rebours (BNE : Banch if Not Equal to zero)
Prédictions
Nombre de fois que la boucle s'exécute : 5 fois
Valeur finale de cmpt : 00
Q8. Tableau d'exécution de la boucle
| Passage | A avant DECA | A après DECA | Flag Z | Branchement ? | Commentaire |
|---|---|---|---|---|---|
| 1 | 05 | 04 | 0 | OUI | Continue |
| 2 | 04 | 03 | 0 | OUI | Continue |
| 3 | 03 | 02 | 0 | OUI | Continue |
| 4 | 02 | 01 | 0 | OUI | Continue |
| 5 | 01 | 00 | 1 | NON | Sort de la boucle |
Conclusion : Pour sortir de la boucle, il faut que Z = 1 (condition de BNE).
BNE signifie "Branch if Not Equal to zero", donc on continue tant que Z=0 et on sort quand Z=1.
Algorigramme de la boucle
- Terminateur (ellipse) : Début et Fin du programme
- Traitement (rectangle) : Opérations d'affectation ([A] ← 5, [A] ← [A] - 1)
- Test (losange) : Condition de boucle ([A] ≠ 0 ?)
- Étiquette (rectangle arrondi) : Point de retour de la boucle (loop)
- Flèches : Sens d'exécution (verte = OUI, rouge = NON)
B.3 - Boucles avec adressage indexé
🧪 Exercice B.3.1 - Lire trois octets consécutifs dans la mémoire
Q9. Analyse du programme et synthèse dans un tableau
| Instruction | X (hexa) | A (hexa) | B (hexa) | Donnée pointée | Adresse |
|---|---|---|---|---|---|
| ldx #data | 0020 | - | - | 0A (10) | 0020 |
| ldaa 0,X | 0020 | 0A | - | 0A (10) | 0020 |
| inx | 0021 | 0A | - | 14 (20) | 0021 |
| ldab 0,X | 0021 | 0A | 14 | 14 (20) | 0021 |
| inx | 0022 | 0A | 14 | 1E (30) | 0022 |
| ldaa 0,X | 0022 | 1E | 14 | 1E (30) | 0022 |
Conclusion :
- Le registre X contient une adresse
- L'instruction LDAA 0,X signifie : lire la donnée à l'adresse 0 + [X]
- INX permet de passer à l'octet suivant
Avantage : L'adresse change dynamiquement → parfait pour les boucles !
🧪 Exercice B.3.2 - Afficher une chaînes de caractères
Q10. Parcours avec test de fin (version avec compteur)
| Passage | X (hexa) | A (hexa) | B (hexa) | Caractère |
|---|---|---|---|---|
| 1 | 0020 | 48 | 5 | 'H' |
| 2 | 0021 | 65 | 4 | 'e' |
| 3 | 0022 | 6C | 3 | 'l' |
| 4 | 0023 | 6C | 2 | 'l' |
| 5 | 0024 | 6F | 1 | 'o' |
Q11. Détection du caractère NUL
Q11.a) Algorigramme complété
L'algorigramme montre :
- [X] ← msg (initialisation du pointeur X avec l'adresse du premier caractère du message)
- Début de la boucle (loop)
- [A] ← [0 + [X]] (lire le caractère pointé par X)
- Test : [A] = 0 ? (Z=1 ?)
- Si OUI → brancher à suite (fin de chaîne détectée)
- Si NON → [X] ← [X] + 1 (passer au caractère suivant)
- Retour à loop
Q11.b) Code assembleur complété
Q11.c) Fichier finchaine.asm complété
Q11.d) Affichage dans le simulateur
Pour afficher "Hello" dans l'onglet du simulateur, il faut utiliser transférer chaque
caractère
de la zone mémoire $0020:$0024 à la zone mémoire $FB00:$FB04.
- Une chaîne de caractères est terminée par le caractère
NUL (00₁₆) - La directive
.strajoute automatiquement le NUL - On utilise le registre
Xcomme pointeur pour parcourir la chaîne - On teste chaque caractère pour détecter la fin (
cmpa #0) - Cette technique évite de devoir connaître la longueur à l'avance
B.4 - Sous-programme
🧪 Exercice B.4.1 - Effacer l'écran du simulateur
Q12.a) Identification du sous-programme
Le sous-programme à entourer s'étend de l'étiquette cls jusqu'à l'instruction
rts :
; Programme principal
Fonction : Efface une zone mémoire en la remplissant d'espaces (caractère
ASCII
$20).
Q12.b) Instruction d'appel du sous-programme
L'instruction utilisée est : bsr
(cls pour le retour)
Signification : BSR = Branch to SubRoutine (Sauter vers un sous-programme)
Fonctionnement :
- Sauvegarde l'adresse de retour sur la pile
- Saute à l'étiquette
cls - Le
rts(ReTurn from Subroutine) restaure l'adresse et continue après lebsr
Q12.c) Analyse de la zone effacée
Zone effacée : [$FB00 ; $FB0F] soit 16 octets
| Constante | Valeur | Description |
|---|---|---|
bscreen |
$FB00 | Adresse de début (incluse) |
escreen |
$FB10 | Adresse de fin (exclue) |
| Taille | 16 octets | $FB10 - $FB00 = 16 |
Explication : La boucle s'arrête quand
X = escreen ($FB10), donc le dernier octet effacé est à $FB0F. Cela représente
seulement 16 caractères sur une ligne qui en contient 50.
Q12.d) Modification pour effacer complètement la première ligne
Modification à effectuer : Changer la valeur de escreen
Aucune autre modification n'est nécessaire ! Le sous-programme utilisera automatiquement la nouvelle valeur.
Q12.e) Algorigramme du programme principal
• Ovale : Terminateur (début/fin de programme)
• Rectangle arrondi : Traitement (opération, instruction)
• Rectangle avec bordures verticales vides : Sous-programme prédéfini
• Losange : Décision (test conditionnel)
Note : Les crochets [ ] représentent le contenu d'une adresse mémoire ou d'un registre. Par exemple, [A] signifie le contenu de l'accumulateur A, et [[X]] signifie le contenu de la mémoire à l'adresse pointée par X.
📝 Récapitulatif des flags et instructions
Les 4 flags principaux
| Flag | Nom | Signification | Utilisé pour |
|---|---|---|---|
| Z | Zero | Résultat = 0 | Tester l'égalité, détecter la fin de boucle |
| N | Negative | Bit 7 = 1 | Détecter un nombre négatif (complément à 2) |
| V | oVerflow | Dépassement signé | Détecter dépassement en arithmétique signée |
| C | Carry | Retenue | Détecter dépassement en arithmétique non signée |
Instructions de branchement
| Instruction | Signification | Condition | Utilisation |
|---|---|---|---|
| BRA | Branch Always | Toujours | Saut inconditionnel |
| BEQ | Branch if Equal | Z = 1 | Brancher si résultat = 0 |
| BNE | Branch if Not Equal | Z = 0 | Brancher si résultat ≠ 0 (boucles) |
| BSR | Branch to SubRoutine | - | - |
Modes d'adressage vus
| Mode | Syntaxe | Exemple | Description |
|---|---|---|---|
| Immédiat | #valeur | ldaa #200 | Charger une valeur directe |
| Étendu | adresse | ldaa $0020 | Lire à une adresse fixe |
| Indexé | offset,X | ldaa 0,X | Lire à l'adresse offset + [X] |
| Relatif | offset | bsr sp | Exécuter le sous-programme à partir de [PC] + offset (offset en complément à 2) |
Pour créer une boucle efficace :
- Initialiser un compteur ou un pointeur
- Créer une étiquette pour le début de la boucle
- Effectuer les opérations souhaitées
- Modifier le compteur/pointeur (DECA, INX...)
- Tester la condition de sortie
- Brancher conditionnellement au début (BNE, BEQ...)