Sujets T DTP
Sujets T DTP
Sujets T DTP
Documentation Technique
Sujets des Travaux Dirigés
Sujets des Travaux Pratiques
Année Universitaire 2017 / 2018
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 1
Table des matières
I Documentation Technique 4
II Travaux Dirigés 23
1 TD séance 1 : Codage 24
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 2
6 TP séances 8, 9 et 10 : Procédures, fonctions et paramètres 101
IV Annexes 121
4 Annexe III : Spécification des fonctions d’entrée/sortie définies dans es.s 125
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 3
Première partie
Documentation Technique
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 4
Chapitre 1
Depuis une machine de type POSIX (unix, linux, macOS) : lancer la commande ssh -X -C
turing.e.ujf-grenoble.fr dans un terminal (Xterm, Konsole, etc) pour vous connecter.
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 5
— Il doit ensuite exécuter sous son identité la commande :
source /Public/401 INF PUBLIC/config.sh
1.5.2 Outils
— nedit : création et modification de fichiers au format texte (gedit également disponible)..
— cat et less : visualisation de fichiers texte.
— bitmap : affichage d’une image monochrome au format bitmap.
— xli : visualisation de fichiers contenant une image.
— hexdump : visualisation en hexadécimal d’un fichier binaire ou texte.
— arm-eabi-gcc : compilateur C et assembleur pour processeur Arm.
— arm-eabi-objdump : utilitaire permettant d’observer le contenu d’un fichier binaire ayant été
produit par arm-eabi-gcc.
— Renommer un fichier :
mv <nom original du fichier > <nouveau nom du fichier >
Exemple : mv fich1.c fich2.c
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 6
— Déplacer un fichier :
mv <nom du fichier > <nom du répertoire destination>
Exemple : mv fich1.c ../repB
— Afficher (sans le modifier) le contenu d’un gros fichier (inutile d’utiliser nedit) :
less <nom du fichier > Exemple : less fich1.c
— Afficher (sans le modifier) le contenu d’un petit fichier (inutile d’utiliser nedit) :
cat <nom du fichier > Exemple : cat fich2.s
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 7
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 8
Chapitre 2
31 28 76 4 0
NZCV IF mode
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 9
d’information entre les registres et la mémoire (paragraphe 2.1.7).
Les instructions sont codées sur 32 bits.
Certaines instructions peuvent modifier les codes de conditions arithmétiques N, Z, C, V en ajou-
tant un S au nom de l’instruction.
Toutes les instructions peuvent utiliser les codes de conditions arithmétiques en ajoutant un
mnémonique (Cf. figure 2.2) au nom de l’instruction. Au niveau de l’exécution, l’instruction est
exécutée si la condition est vraie.
Toute instruction peut être exécutée sous une des conditions décrites dans la figure 2.2. Le code
de la condition figure dans les bits 28 à 31 du code de l’instruction. Par défaut, la condition est AL.
opérande commentaire
#immédiate-8 entier sur 32 bits (Cf. remarque ci-dessous)
rm registre
rm, shift #shift-imm-5 registre dont la valeur est décalée d’un nombre
de positions représenté sur 5 bits
rm, shift rs registre dont la valeur est décalée du nombre
de positions contenu dans le registre rs
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 10
Dans la table précédente le champ shift de l’opérande peut être LSL, LSR, ASR, ROR qui signi-
fient respectivement “logical shift left”, “logical shift right”, “arithmetic shift right”, “rotate right”.
Une valeur immédiate est notée selon les mêmes conventions que dans le langage C ; ainsi elle peut
être décrite en décimal (15), en hexadécimal (0xF) ou en octal (O17).
Le codage de l’instruction MOV est décrit dans les figures 2.3 et 2.4. <COND> désigne un mnémonique
de condition ; s’il est omis la condition est AL. Le bit S est mis à 1 si l’on souhaite une mise à jour des
codes de conditions arithmétiques. Le bit I vaut 1 dans le cas de chargement d’une valeur immédiate.
Les codes des opérations LSL, LSR, ASR, ROR sont respectivement : 00, 01, 10, 11.
Remarque concernant les valeurs immédiates : Une valeur immédiate sur 32 bits (opérande
#immediate) sera codée dans l’instruction au moyen, d’une part d’une constante exprimée sur 8 bits
(bits 7 à 0 de l’instruction, figure 2.4, 1er cas), et d’autre part d’une rotation exprimée sur 4 bits (bits
11 à 8) qui sera appliquée à la dite constante lors de l’exécution de l’instruction.
La valeur de rotation, comprise entre 0 et 15, est multipliée par 2 lors de l’exécution et permet
donc d’appliquer à la constante une rotation à droite d’un nombre pair de positions compris entre 0
et 30. La rotation s’applique aux 8 bits placés initialement à droite dans un mot de 32 bits (qui n’est
pas celui qui contient l’instruction).
Il en résulte que ne peuvent être codées dans l’instruction toutes les valeurs immédiates sur 32
bits...
Une rotation nulle permettra de coder toutes les valeurs immédiates sur 8 bits.
31 28 27 26 25 24 21 20 19 16 15 12 11 0
cond 00 I 1101 S 0000 rd opérande
11 8 7 0
0000 immediate-8
11 7 65 3 0
shift-imm-5 shift 0 rm
11 8 65 3 0
rs 0 shift 1 rm
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 11
2.1.5 Description des instructions arithmétiques et logiques
31 28 27 26 25 24 21 20 19 16 15 12 11 0
cond 00 I code-op S rn rd opérande
La table ci-dessous donne la liste des intructions arithmétiques et logiques ainsi que les instructions
de chargement d’un registre. Les instructions TST, TEQ, CMP, CMN n’ont pas de registre destination,
elles ont ainsi seulement deux opérandes ; elles provoquent systématiquement la mise à jour des codes
de conditions arithmétiques (dans le codage de l’instruction les bits 12 à 15 sont mis à zéro). Les
instructions MOV et MVN ont un registre destination et un opérande (dans le codage de l’instruction les
bits 16 à 19 sont mis à zéro).
Exemples d’utilisations
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 12
2.1.6 Description des instructions de rupture de séquence
Nous utilisons trois instructions de rupture de séquence : B[<cond>] <déplacement>, BL[<cond>]
<déplacement>, BLX[<cond>] <registre>.
if ConditionPassed(cond) then
PC <-- PC + (SignExtend(déplacement) << 2)
31 28 27 25 24 23 0
cond 101 0 déplacement
Exemples d’utilisations
Dans la pratique, on utilise une étiquette (Cf. paragraphe 2.2.4) pour désigner l’instruction cible
d’un branchement. C’est le traducteur (i.e. l’assembleur) qui effectue le calcul du déplacement.
La figure 2.7 résume l’utilisation des instructions de branchements conditionnels après une com-
paraison.
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 13
b) Instruction BL[<cond>] <déplacement> L’instruction BL provoque la modification du comp-
teur de programme avec sauvegarde de l’adresse de l’instruction suivante (appelée adresse de
retour) dans le registre lr ; le texte suivant est extrait de la documentation ARM :
31 28 27 25 24 23 0
cond 101 1 déplacement
Exemples d’utilisations
Attention : Dans le cadre des TP, l’adresse passée en paramètre à BLX doit être paire. En effet,
l’exécution de BLX avec une adresse impaire active un mode spécial du processeur (THUMB) avec un
autre jeu d’instructions (codées sur 16 bits). Ce type d’erreur peut avoir des effets assez variés en
fonction du programme concerné : on peut obtenir un message d’erreur relatif au mode THUMB ou
un comportement arbitraire du simulateur.
Exemples d’utilisations
Pour désigner une procédure on utilisera une étiquette ; des exemples sont donnés dans le para-
graphe 2.2.4.
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 14
mode-adressage opération effectuée
[rn] rd <– mem [rn]
[rn, #offset12] rd <– mem [rn + offset12]
[rn, #-offset12] rd <– mem [rn - offset12]
[rn, rm] rd <– mem [rn + rm]
[rn, -rm] rd <– mem [rn - rm]
Il existe des variantes de l’instruction LDR permettant d’accéder à un octet : LDRB ou à un mot
de 16 bits : LDRH. Et si l’on veut accéder à un octet signé : LDRSB ou à un mot de 16 bits signé :
LDRSH. Ces variantes imposent cependant des limitations d’adressage par rapport aux versions 32 bits
(exemple : valeur immédiate codée sur 5 bits au lieu de 12).
Pour réaliser le transfert inverse, registre vers mémoire, on trouve l’instruction STR et ses variantes
STRB et STRH. La syntaxe est la même que celle de l’instruction LDR. Par exemple, l’instruction STR
rd, [rn] provoque l’exécution : MEM [rn] <-- rd.
Exemples d’utilisations
L’instruction LDR est utilisée entre autres pour accéder à un mot de la zone text en réalisant
un adressage relatif au compteur de programme. Ainsi, l’instruction LDR r2, [pc, #depl] permet de
charger dans le registre r2 avec le mot mémoire situé à une distance depl du compteur de programme,
c’est-à-dire de l’instruction en cours d’exécution. Ce mode d’adressage nous permet de recupérer
l’adresse d’un mot de données (Cf. paragraphe 2.2.4).
Les instructions LDR et STR offrent des adressages post-incrémentés et pré-décrémentés qui per-
mettent d’accéder à un mot de la mémoire et de mettre à jour une adresse, en une seule instruction.
Cela revient à combiner un accès mémoire et l’incrémentation du pointeur sur celle-ci en une seule
instruction.
instruction ARM équivalent ARM équivalent C
LDR r1, [r2, #-4]! SUB r2, r2, #4 r1 = *--r2
LDR r1, [r2]
LDR r1, [r2], #4 LDR r1, [r2] r1 = *r2++
ADD r2, r2, #4
STR r1, [r2, #-4]! SUB r2, r2, #4
STR r1, [r2]
STR r1, [r2], #4 STR r1, [r2]
ADD r2, r2, #4
La valeur à incrémenter ou décrémenter (4 dans les exemples ci-dessus) peut aussi être donnée
dans un registre.
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 15
Transfert multiples
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 16
adresses 0 0
croissantes
r7
r3
r4
r5
r6
r7
max max
a) b)
Figure 2.9 – Transfert multiples mémoire/registres : STMFD r7!, {r3,r4,r5,r6} ou (STMDB ...)
permet de passer de l’état a) de la mémoire à l’état b). LDMFD r7!, {r3,r4,r5,r6} (ou LDMIA ...)
réalise l’inverse.
.data
@ déclaration de données
@ ...
.text
@ des instructions
@ ...
Exemple :
.data
.word 4536 @ déclaration de la valeur 4536 sur 32 bits (1 mot)
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 17
.hword -24 @ déclaration de la valeur -24 sur 16 bits (1 demi mot)
.byte 5 @ déclaration de la valeur 5 sur 8 bits (1 octet)
.word 0xfff2a35f @ déclaration d’une valeur en hexadécimal sur 32 bits
.byte 0xa5 @ idem sur 8 bits
On peut aussi déclarer des chaı̂nes de caractères suivies ou non du caractère de code ASCII 00.
Un caractère est codé par son code ASCII (Cf. paragraphe 1).
Exemple :
.data
.ascii "un texte" @ déclaration de 8 caractères...
.asciz "un texte" @ déclaration de 9 caractères, les m^
emes que ci-dessus
@ plus le code 0 à la fin
La définition de données doit respecter les règles suivantes, qui proviennent de l’organisation phy-
sique de la mémoire :
— un mot de 32 bits doit être rangé à une adresse multiple de 4
— un mot de 16 bits doit être rangé à une adresse multiple de 2
— il n’y a pas de contrainte pour ranger un octet (mot de 8 bits)
Pour recadrer une adresse en zone data le langage d’assemblage met à notre disposition la directive
.balign.
Exemple :
.data
@ on note AD l’adresse de chargement de la zone data
@ que l’on suppose multiple de 4 (c’est le cas avec les outils utilisés)
.hword 43 @ après cette déclaration la prochaine adresse est AD+2
.balign 4 @ recadrage sur une adresse multiple de 4
.word 0xffff1234 @ rangé à l’adresse AD+4
.byte 3 @ après cette déclaration la prochaine adresse est AD+9
.balign 2 @ recadrage sur une adresse multiple de 2
.hword 42 @ rangé à l’adresse AD+10
On peut aussi réserver de la place en zone .data ou en zone .bss avec la directive .skip.
.skip 256 réserve 256 octets qui ne sont pas initialisés lors de la réservation. On pourra par programme
écrire dans cette zone de mémoire.
.text
.global main
main:
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 18
2.2.4 Utilisation d’étiquettes
Une donnée déclarée en zone data ou bss ou une instruction de la zone text peut être précédée
d’une étiquette. Une étiquette représente une adresse et permet de désigner la donnée ou l’instruction
concernée.
Les étiquettes représentent une facilité d’écriture des programmes en langage d’assemblage.
DD: .word 5
.text
@ plus loin
relais: .word DD @ déclaration de l’adresse DD en zone text
L’instruction LDR r1, relais est codée avec un adressage relatif au compteur de programme :
LDR r1, [pc, #depl] (Cf. paragraphe 2.1.7).
...
ma_proc: @ corps de la procedure
mov pc, lr
...
@ appel de la procedure ma_proc
BL ma_proc
On utilise l’instruction BLX lorsque l’adresse de la procédure est rangée dans un registre, par
exemple lorsqu’une procédure est passée en paramètre :
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 19
LDR r1, adr_proc @ r1 <-- adresse ma_proc
BLX r1
...
adr_proc: .word ma_proc
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 20
arm-eabi-as -o prog.o prog.s. Elles produisent toutes deux un fichier objet prog.o sans les infor-
mations nécessaires à l’exécution sous débogueur.
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 21
Et ne pas oublier : man gdb sous Unix (ou Linux) et quand on est sous gdb : help
nom de commande. . .
Pour lancer ddd : ddd --debugger arm-eabi-gdb. On obtient une grande fenêtre avec une par-
tie dite “source” (en haut) et une partie dite “console” (en bas). Dans la fenêtre “console” taper
successivement les commandes : file prog, target sim et enfin load.
On voit apparaı̂tre le source du programme en langage d’assemblage dans la fenêtre “source” et
une petite fenêtre de “commandes”. Maintenant on peut commencer la simulation.
Toutes les commandes de gdb sont utilisables soit en les tapant dans la fenêtre “console”, soit en
les sélectionnant dans le menu adéquat. On donne ci-dessous la description de quelques menus. Pour
le reste, il suffit d’essayer.
— placer un point d’arrêt : sélectionner la ligne en question avec la souris et cliquer sur l’icône
break (dans le panneau supérieur).
— démarrer l’exécution : cliquer sur le bouton Run de la fenêtre “commandes”. Vous voyez ap-
paraı̂tre une flèche verte qui vous indique la position du compteur de programme i.e. où en est
le processeur de l’exécution de votre programme.
— le bouton Step permet l’exécution d’une ligne de code, le bouton Next aussi mais en entrant
dans les procédures et le bouton Cont permet de poursuivre l’exécution.
— enlever un point d’arrêt : se positionner sur la ligne désirée et cliquer à nouveau sur l’icône
break.
— voir le contenu des registres : sélectionner dans le menu Status : Registers ; une fenêtre apparaı̂t.
La valeur contenue dans chaque registre est donnée en hexadécimal (0x...) et en décimal.
— observer le contenu de la memoire étiquettée etiquette : apres avoir sélectionné memory dans
le menu Data, on peut soit donner l’adresse en hexadecimal 0x... si on la connaı̂t, soit donner
directement le nom etiquette dans la case from en le précédant du caractère &, c’est-à-dire
&etiquette.
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 22
Deuxième partie
Travaux Dirigés
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 23
Chapitre 1
TD séance 1 : Codage
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 24
ROUGE
VIOLET BLEU
BLANC
JAUNE CYAN
VERT
1. on ne dit pas décimale car ce mot est impropre ici mais c’est quand même le mot habituel
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 25
Chapitre 2
2.1 Introduction
Un entier E peut être représenté par uneP suite de n chiffres (ou digits) ei , tous inférieurs à la base
n−1
utilisée (0 ≤ ei ≤ B − 1) et tels que E = i=0 ei ∗ B i . Chaque chiffre ei représente le reste de la
i
division entière de E/B par B. La base B est éventuellement précisée en indice à droite du dernier
chiffre ou entre parenthèses. Par défaut, il s’agit de la base 10.
L’entier composé des k chiffres de poids faibles de E est E modulo 1 2k et celui composé des n-k
chiffres de poids forts de E est E / 2k . Exemple pour n=5 et k=2 :
2310 = 5 ∗ 4 + 3 = 101112 . (10111) : 23/4 = 5 = 1012 . 23 modulo 4 = 3 = 112
Les organes d’un ordinateur sont dimensionnés à un nombre fixe n de bits. Par exemple, les
registres, les unités de calcul, le bus d’accès à la mémoire d’un ARM7 sont tous dimensionnés à 32
bits : le résultat d’une opération est stocké avec le même nombre de bits que ses opérandes. Tous les
calculs sont donc réalisés modulo 2n (environ quatre milliards pour n = 32 bits).
La table en annexe 2 donne les principales puissances de 2, ainsi que la valeur binaire et décimale
de chaque chiffre hexadécimal.
Exemples :
17810 = B216 : 178/16 quotient 11, reste 2 (poids f aible), 11/16 : quotient 0 reste 11( B (poidsf ort))
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 26
1110 = 10112 = 5 ∗ 2 + 1 (poids f aible), 5 = 2 ∗ 2 + 1 , 2 = 1 ∗ 2 + 0 , 1 = 0 ∗ 2 + 1 (poids f ort)
10011011012 → 0010 0110 1101 → 26B16
n−1 n−1
X an − 1 X
ai = et 2i = 2n − 1
a−1
i=0 i=0
En effet (an−1 + an−2 + ... + a1 + 1)(a − 1) = n
(a − an−1 + an−1 − an−2 . . . + a − 1) = (an − 1))
2.1.2 Compléments à 1 et à 2
Soit E = n−1 i
P
i=0 ei ∗ 2 un entier naturel représenté sur n chiffres en base
Pn 2. On appelle complément
n
à 2 − 1 de E (on dit habituellement complément à 1 de E) l’entier E = i=0 ei obtenu en remplaçant
les 1 par des 0 et les 0 parP 1 − ei ) dans la représentation
des 1 (ei = P en binaire de E. Il s’écrit ˜E en
langage C. On a E + E = ni=0 ei 2i + ni=0 (1 − ei )2i = i=0
Pn−1 i
2 = 2n − 1, d’où E = 2n − 1 − E.
2.2 Addition
On rappelle le principe de calcul dans l’addition : colonne par colonne, de droite à gauche. Les
retenues, habituellement placées au dessus de l’opérande gauche, sont placées ici en dessous de
l’opérande droit. Dans chaque colonne, on fait la somme des chiffres du premier (ai ) et du deuxième
(bi ) opérande, ainsi que la retenue entrante (ci ).
3 6 4 3 3 6 4 3
+10 5 7 8 5 5 7 8 5
C=0 1 1 0 0 C=0 1 ←1 1 ←1 0 ←0 0
9 4 2 8 9 < 10 9 14 ≥ 10 4 12 ≥ 10 2 8 < 10 8
0 1 1 1 0 1 1 1
+2 0 1 1 0 0 1 1 0
C=0 1 1 0 0 C=0 1 ←1 1 ←1 0 ←0 0
1 1 0 1 1< 2 1 3≥ 2 1 2≥ 2 0 1<2 1
2. ∀i, ei = 1 ⇒ i ≥ u, (u=0 si E=0)
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 27
Dans une addition normale, la retenue entrante initiale (c0 , colonne de droite) est nulle. L’utilisa-
tion d’une retenue initiale à 1 permet de calculer l’expression opgauche + opdroit + 1 (pour réaliser des
soustractions par addition du complément à deux).
1 1 0 1 1 1 0 1
+2 1 0 0 1 1 0 0 1
C=1 0 0 1 1 C=1 0 ←0 0 ←0 1 ←1 1
0 1 1 1 2≥ 2 0 1< 2 1 1< 2 1 3≥2 1
0 1 0 0 0 1 0 0
+2 1 0 1 0 1 0 1 0
C=0 0 0 0 1 C=0 0 ←0 0 ←0 0 ←0 1
1 1 1 1 1< 2 1 1< 2 1 1< 2 1 1<2 1
Les règles de calcul pour l’addition et la soustraction sont les mêmes quel que soit α : seule
l’interprétation des valeurs des opérandes et du résultat change.
Pi=n−1
2.3.1 Pour entiers naturels (N) : α = 1 et E = i=0 ei 2i .
En pratique, il n’est pas rare que les entiers manipulés dans la vie courante sortent de l’intervalle
de valeurs représentables dans les formats inférieurs à 64 bits. A titre d’exemple, les capitalisations
boursières des sociétés ne sont pas toutes représentables sur 32 bits.
Pour stocker une valeur entière toujours positive ou nulle 3 , le programmeur peut décider
d’utiliser une variable entière en interprétant son contenu comme un entier naturel (attribut unsi-
gned de type entier en langage C) afin de maximiser l’intervalle de valeurs représentables : [0 . . . 2n −1].
Le bit de poids fort n’a pas de signification particulière : il indique simplement si la valeur
représentée est supérieure à 2n−1 ou pas.
Dans le langage C, le type entier naturel est spécifié avec l’attribut unsigned, ou les types entier
naturel de taille précise uintxx t (x ∈ {8, 16, 32, 64} ) définis dans stdint.h (révisions récentes du
langage).
La figure en cercle 2.1 illustre les 24 = 16 codes binaires possibles sur 4 bits (incluses dans le
cercle intérieur) et (sur la couronne extérieure,en décimal) les valeurs d’entiers naturels représentées.
Chaque entier correspond à un angle de rotation depuis l’origine dans le sens trigonométrique 4 .
L’addition de 2 entiers peut être interprétée comme la sommation des angles de rotation des
opérandes. A partir d’un tour complet, il y a débordement (résultat apparent obtenu modulo 24 et
C=1 qui indique qu’il faudrait un bit de plus (à 1) pour représenter le vrai résultat).
3. Les constantes adresse et les variables pointeurs entrent dans cette catégorie.
4. ou anti-horaire
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 28
12 11
13 −4 −5 10
−3 −6
1100 1011
14 1101 1010 9
−2 −7
1110
−
1001
15 −1 8
1111 1000 −8
0000 0111
0 +0 +7 7
0001 0110
+1
+
0101 +6
1 0010 6
0011 0100
+2 +5
2 +3 +4 5
3 4
C’est pourquoi les entiers relatifs sont codés selon la méthode du complément à 2.
Le bit de poids fort représente maintenant le signe de l’entier et le principe consiste à retrancher
2n à la valeur associée aux entiers dont le bit de poids fort est à 1. Cette convention représente les
entiers négatifs selon la technique du complément à deux 6 : l’entier relatif -x est représenté comme
l’entier naturel 2n − x. Dans les langages, cette convention d’interprétation est généralement utilisée
par défaut (type entier sans attribut unsigned ou type intxx t en langage C).
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 29
Un entier E dont le bit de signe est 1 (< 0) appartient à l’intervalle [−2n−1 , +2n−1 − 1] et sa
valeur associée est −e2 = −(2n − e).
— Pour calculer l’opposé d’un entier, il faut prendre le complément à deux de cet entier (et non
inverser simplement le bit de signe).
— Sur n bits, l’entier −2n−1 est son propre complément à deux et l’entier relatif +2n−1 n’est pas
représentable.
— L’ajout d’un bit à 0 en poids fort d’un entier relatif négatif inverse son signe et change sa valeur.
La couronne intérieure de la figure 2.1 illustre le codage des entiers relatifs sur 4 bits. A chaque
entier peut être associé un angle de rotation dans le sens trigonométrique pour les entiers positifs ou
nuls et dans le sens horaire pour les entiers négatifs.
Le code 1001 peut représenter selon la convention d’interprétation soit l’entier naturel 9 soit
l’entier relatif -7. De même, 0101 est le code commun aux entiers naturels 5 et relatif +5.
L’addition de deux entiers relatifs de même signe donne une erreur lorsque la somme des angles
correspondant aux entiers va au-delà d’une rotation d’un demi-tour, avec un résultat apparent de
signe opposé à celui des opérandes. Cette erreur vient du fait que le résultat attendu n’appartient pas
à l’intervalle des valeurs représentables sur le nombre de bits de codage utilisé.
Pour les bornes de l’intervalle sur 64 bits, le tableau mentionne l’ordre de grandeur (préfixé par) :
la valeur exacte représente une vingtaine de chiffres. Les préfixes Kb (kilo) et Mb (méga) représentent
210 = 102410 et 220 = 104857610 , dont la valeur est proche de 1000 (1K) et 1000000 (1M). Même
principe pour Gb (giga : 230 ) et Eb (eta : 260 ).
La réduction de format élimine les bits de poids forts excédentaires (opération modulo). La valeur
entière n’est pas modifiée si elle est représentable sur le contenant de plus petite taille.
En sens inverse, la représentation de l’entier doit être étendue en ajoutant des bits de poids forts
selon la nature de l’entier :
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 30
— ajout de bits à 0 pour un entier naturel
— duplication de l’ancien bit de poids fort (bit de signe) pour un entier relatif
Il existe ainsi 3 instructions ARM de transfert d’un entier entre un registre 32 bits regx et un
emplacement de 16 bits en mémoire mem[y]. L’instruction ldrh est destinée aux entiers naturels codés
sur 16 bits, et ldrsh aux entiers relatifs.
— strh : regx modulo 216 → mem[y]
— ldrh : regx extension en ajoutant 16 f ois un bit 0 mem[y]
←−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
— ldrsh : regx extension en ajoutant 16 f ois le bit de poids f ort de mem[y]
←−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Remarque : l’entier 2k est l’entier 1 décalé de k bits à gauche (((uint32 t)1 k) en C).
Une opération de rotation est un décalage dans lequel les bits ajoutés à une extrémité sont ceux
qui sont éjectés de l’autre extrémité de l’entier. Une rotation à gauche de k bits et une rotation à
droite de n − k bits ont le même effet.
Le décalage de k bits à droite correspond à la division par 2k : les k bits de poids faibles sont éjectés.
Le décalage logique de k bits à droite (Logic Shift Right #k en langage d’assemblage ARM, k
sur une variable unsigned en C) est destiné aux entiers naturels : k bits à 0 sont ajoutés en poids
forts et l’entier est divisé par 2k .
Le décalage arithmétique à droite (Arithmetic Shift Right en langage d’assemblage ARM) est
destiné aux entiers relatifs : le bit de poids fort (signe) d’origine est recopié dans les bits ajoutés à
gauche. L’entier est divisé par 2k s’il en était un multiple au départ.
La négation (un seul opérande) bit à bit (˜ en C) inverse tous les bits de l’entier : elle réalise le
complément à 1 de celui-ci.
Les autres opérations booléennes classiques à 2 deux opérandes existent aussi en version bit à bit :
— Et bit à bit (& en C)
— Ou bit à bit (— en C)
— Ou exclusif bit à bit (ˆ en C, remarquer que ce n’est pas l’opérateur d’élévation à la puissance)
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 31
2.4.4 Exemples d’application
Tous les entiers des exemples suivant sont supposés déclarés de type unsigned.
Création de masque : entier dont les bits x à y (y ≥ x) inclus sont à 0, les autres à 1 (utilisé dans
un ET bit à bit, permet de forcer à 0 les bits x à y d’un entier) :
2.5 Soustraction
Dans chaque colonne, on fait la somme du chiffre du deuxième (bi ) opérande et de l’emprunt
entrant (ei ) et l’emprunt entrant initial e0 est nul. Le chiffre (ri ) du résultat est égal :
— au chiffre du premier opérande (ai ) moins cette somme, l’emprunt sortant (ei+1 ) étant 0, si
somme ≤ ai ,
— au chiffre du premier opérande (ai ) plus la base moins cette somme, l’emprunt sortant (ei+1 )
étant 1, si somme > ai ,
a3 a2 a1 a0 opérande gauche ai
+base b3 b2 b1 b0 opérande droit bi
E = e4 e3 e2 e1 e0 emprunts sortant ei+1 ei entrant
r3 r2 r1 r0 résultat apparent ri
8 6 4 8 8 6 4 8
−10 5 7 9 5 5 7 9 5
E=0 1 1 0 0 E=0 1 ←1 1 ←1 0 ←0 0
2 8 5 3 6≤8 2 8>6 8 9>4 5 5≤8 3
1 1 0 1 1 1 0 1
−2 0 1 1 0 0 1 1 0
E=0 1 1 0 0 E=0 1 ←1 1 ←1 0 ←0 0
0 1 1 1 0≤1 0 2>1 1 1>0 1 0≤1 1
0 1 0 0 0 1 0 0
−2 0 1 0 1 0 1 0 1
E=1 1 1 1 0 E=1 1 ←1 1 ←1 1 ←1 0
1 1 1 1 1>0 0 2>1 1 1>0 1 1>0 1
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 32
2.6 Soustraction par addition du complément à deux
En pratique, toutes les soustractions sont réalisées par addition du complément à 2. On exploite
la propriété suivante (calculs sur n bits) : x + y 2 = x + 2n − y.
Les résultats étant obtenus modulo 2n , on peut calculer l’expression x−y en effectuant une addition
comme suit :
— Premier opérande : x
— Deuxième opérande : y
— Retenue initiale : 1 (pour faire x + y + 1)
— On observe que la ligne des retenues dans cette addition de y est le complément de la ligne des
emprunts dans la soustraction normale.
Le calcul de 13 − 6 (réalisable) et 4 − 5 (impossible pour des entiers naturels) est illustré par les
deux derniers exemples des paragraphes 2.5 (soustraction normale) et 2.2 (soustraction par addition
du complément à deux).
Après une addition, C = 1 indique un débordement : le résultat de l’opération est trop grand
pour être représentable sur n bits. Le résultat apparent est alors faux : il correspond au vrai résultat
à 2n près.
E est le dernier emprunt sortant d’une soustraction. E = 1 indique que la soustraction est im-
possible parce que le deuxième opérande est supérieur au premier. Les soustractions sont en pratique
réalisées par addition du complément à deux. C correspond alors à E. Après une soustraction par
addition du complément à deux, C = 0 indique que la soustraction est impossible, C = 1 que
l’opération est correcte 7 .
7. Attention : les instructions de soustraction ou de comparaison de certains processeurs (dont le SPARC) stockent
dans C le complément de la retenue finale. Pour ces processeurs, C = 1 indique toujours une erreur, que ce soit après
une addition ou une soustraction.
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 33
2.7.4 Débordement en convention d’entiers relatifs : V
Pour les entiers, la soustraction est toujours réalisée par addition de l’opposé du deuxième opérande.
La valeur absolue de la somme de deux entiers relatifs de signes opposés est inférieure ou égale à la
la plus grande des valeurs absolues des opérandes et le résultat est toujours représentable sur n bits.
La somme de deux entiers relatifs de même signe peut ne pas être représentable sur n bits, auquel cas
le résultat apparent sera faux :
— Sa valeur n’est égale à celle du vrai résultat de l’opération qu’à 2n près.
— Son bit de signe (bit de poids fort) est également faux : la somme de deux entiers positifs
donnera un résultat apparent négatif et la somme de deux entiers négatifs donnera un résultat
apparent positif ou nul.
0 0 1 1 +3 0 1 1 0 +6
+2 1 0 1 1 -5 +2 0 1 0 0 +4
V=0 0=0 1 1 0 V=1 6 1
0= 0 0 0
1 1 1 0 -2 1 0 1 0 -6
1 0 1 0 -6
+2 1 1 0 0 -4
V=1 1 6= 0 0 0 0
0 1 1 0 +6
Le signe du vrai résultat (sans erreur) de l’opération s’écrit : V ⊕ N = V .N + V.N . Ainsi, le signe
du résultat de l’opération sans erreur est N signe du résultat apparent s’il n’y a pas de débordement
(V ), ou le signe opposé N de celui du résultat apparent en cas de débordement (V ).
2.8 Exercices
2.8.1 Addition d’entiers naturels
Quels entiers naturels peut-on représenter sur 4 bits ?
Choisir deux entiers naturels représentables sur 4 bits, faire la somme en faisant apparaı̂tre les
retenues propagées. Quand la somme n’est-elle pas représentable sur 4 bits ?
On pourra reprendre l’exercice pour des nombres représentés sur 8, 16 ou 32 bits...
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 34
Quels entiers relatifs peut-on représenter sur 8 bits ? Comment s’y prendre pour coder un entier
relatif en complément à 2 sur 8 bits ? Comment passer d’un relatif négatif à son opposé ?
Choisir un entier relatif positif représentable sur 4 bits. Donnez sa représentation sur 8 bits.
Choisir un entier relatif négatif représentable sur 4 bits. Donnez sa représentation sur 8 bits.
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 35
Chapitre 3
3.1 Sujet du TD
On considère l’instruction : x := (a + b + c) - (x - a - 214).
x, a, b et c sont des variables représentées sur 32 bits et rangées en mémoire aux adresses (fixées
arbitrairement) : 0x50f0 0x2fa0, 0x3804, 0x4050.
Il existe un espace mémoire libre à partir de l’adresse 0x6400.
On veut écrire un programme en langage machine qui exécute l’instruction considérée. Le pro-
gramme ne doit pas changer les valeurs des variables a, b et c (i.e. ne doit pas changer le contenu des
cases mémoire correspondantes).
Exercice : Dans chacun des langages machines décrits dans la suite, écrire systématiquement le
programme qui exécute l’instruction ci-dessus.
Par ailleurs, on peut aussi charger une information dans l’accumulateur depuis la mémoire ou avec
une valeur appelée valeur immédiate.
instruction opération réalisée
load adr ACC <-- MEM[adr]
load# vi ACC <-- vi
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 36
BUS DONNEES
0x0000
opérande
instructions
UAL
registre
instruction
ACC BUS ADRESSES 0x2fa0 valeur de a
0x3804 valeur de b
0x4050 valeur de c données
0x6400 libre
si besoin
0xffff
MEMOIRE
1. Calculer la taille du programme si on suppose que les adresses sont représentées sur 16 bits (2
octets), les valeurs immédiates sont aussi représentées sur 2 octets et le code instruction est lui
codé sur 1 octet.
2. Quelle est la différence entre sub 0x2fa0 et sub# 214 ?
3. Une instruction store# 6 a-t-elle une signification ?
4. Ecrire un programme qui réalise le même calcul en commençant par évaluer la soustraction.
Les microprocesseurs des années 70/80 ressemblent à ce type de machine : type 6800, 6501 (APPLE
2), Z80. Il en existe encore dans les petits automatismes, les cartes à puce, ... Les adresses sont souvent
sur 16 bits, les instructions sur 1,2,3,4 octets, le code opération sur 1 octet.
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 37
BUS DONNEES
0x0000
opérande1 opérande2 registre
instruction
instructions
UAL
R0
R1
opérande_dest R2 BUS ADRESSES 0x2fa0 valeur de a
0x3804 valeur de b
0x4050 valeur de c données
0x6400 libre
si besoin
0xffff
MEMOIRE
Une instruction de calcul est formée du code de l’opération à réaliser, et de la désignation des
registres intervenant dans le calcul. On trouve deux formes de telles instructions :
— deux opérandes sources dans des registres (on écrira regs1 et regs2) et un registre pour le
résultat du calcul (on écrira regd pour registre destination).
— un opérande source dans un registre et l’autre donné dans l’instruction (valeur immédiate) et
toujours un registre destination.
Au niveau du codage, il faut coder : le code de l’opération à réaliser et les numéros des registres.
Par exemple sur ARM il y a 16 registres, d’où 4 bits pour coder leur numéro.
Nous avons besoin aussi d’effectuer des transferts entre mémoire et registres. En général, dans ce
genre de machine les adresses (et les données) sont représentées sur 32 bits (question d’époque...).
Le problème est que pour représenter l’instruction amener le mot mémoire d’adresse 0x2fa0 dans le
registre 2, il faut : 1 codeop + 1 numéro de registre sur x bits + 1 adresse (0x2fa0) sur 32 bits pour
former l’instruction... codée elle aussi sur 32 bits.
Les opérations de transfert sont réalisées en deux étapes : mettre l’adresse du mot mémoire concerné
dans un registre (ci-dessous reg1) puis charger un registre avec le contenu du mot mémoire à cette
adresse (load) ou ranger le contenu du mot mémoire à cette adresse dans un registre (store).
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 38
1. Si on suppose qu’une instruction est codée sur 4 octets, quelle est la taille du programme ?
2. Discuter de la taille de codage des numéros de registres.
3. Discuter de la taille de codage des valeurs immédiates.
4. Pourquoi en général n’y a-t-il qu’une valeur immédiate ?
Les microprocesseurs des années 90 sont de ce type : machines RISC, type Sparc, ARM. Les
adresses sont en général sur 32 bits, toutes les instructions sont codées sur 32 bits, et il y a beaucoup
de registres.
Remarque : Attention, pour le processeur ARM, dans la syntaxe de l’instruction store les
opérandes sont inversés par rapport au choix fait ci-dessus ; on écrit str reg2, [reg1]. Ainsi l’ordre
d’écriture des opérandes est le même pour l’instruction store (str) et l’instruction load (ldr).
Dans les années 70/80 il y a eu des processeurs (pas micro du tout) de type VAX (inspirés de,
avec beaucoup de variantes). Une instruction peut être codée sur 4 mots de 32 bits et donc contenir
3 adresses.
Il a été construit dans les années 80/90 des microprocesseurs avec deux opérandes pour une ins-
truction : un opérande source servant aussi de destination (type 68000, 8086). Les adresses sont sur
16, 24 ou 32 bits, les instructions sur 1,2,3 ou 4 mots de 16 bits. Le code opération est généralement
sur 1 mot de 16 bits. Il y a 8 ou 16 registres.
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 39
Chapitre 4
Le programme ARM :
.text
.global main
main: ldr r1, ptr_a
ldr r1, [r1]
ldr r2, ptr_b
ldr r2, [r2]
ldr r3, ptr_c
ldr r3, [r3]
add r4, r1, r2
add r4, r4, r3
ldr r2, ptr_x
ldr r3, [r2]
sub r3, r3, r1
sub r3, r3, #214
sub r4, r4, r3
str r4, [r2]
mov pc, lr
.org 0x1000
ptr_a: .word a
ptr_b: .word b
ptr_c: .word c
ptr_x: .word x
.data
.org 0x2fa0
a: .word 10
.org 0x3804
b: .word 20
.org 0x4050
c: .word 30
.org 0x50f0
x: .word 1000
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 40
La directive .org permet de fixer l’adresse relative où sera stockée la valeur qui suit. Par exemple,
le mot étiquetté a sera rangé à l’adresse de début de la zone data + 0x2fa0.
1. Dessiner le contenu de la zone de données en exprimant les valeurs des différentes données en
hexadécimal (en faisant apparaı̂tre les différents octets).
2. Ajouter des commentaires au programme explicitant chacune des lignes de code.
On traduit le programme en binaire en fixant les adresses de début de la zone text et de la zone
data :
La zone text étant stockée à partir de l’adresse 0x800000 (option -Ttext 00800000) et la zone
data à partir de l’adresse 00000000 (option -Tdata 0x0), on regarde la traduction obtenue.
Zone text :
$ arm-eabi-objdump -d -j .text exp_arm
00800000 <main>:
800000: e59f1ff8 ldr r1, [pc, #4088] ; 801000 <ptr_a>
800004: e5911000 ldr r1, [r1]
800008: e59f2ff4 ldr r2, [pc, #4084] ; 801004 <ptr_b>
80000c: e5922000 ldr r2, [r2]
800010: e59f3ff0 ldr r3, [pc, #4080] ; 801008 <ptr_c>
800014: e5933000 ldr r3, [r3]
800018: e0814002 add r4, r1, r2
80001c: e0844003 add r4, r4, r3
800020: e59f2fe4 ldr r2, [pc, #4068] ; 80100c <ptr_x>
800024: e5923000 ldr r3, [r2]
800028: e0433001 sub r3, r3, r1
80002c: e24330d6 sub r3, r3, #214 ; 0xd6
800030: e0444003 sub r4, r4, r3
800034: e5824000 str r4, [r2]
800038: e1a0f00e mov pc, lr
...
00801000 <ptr_a>:
801000: 00002fa0 andeq r2, r0, r0, lsr #31
00801004 <ptr_b>:
801004: 00003804 andeq r3, r0, r4, lsl #16
00801008 <ptr_c>:
801008: 00004050 andeq r4, r0, r0, asr r0
0080100c <ptr_x>:
80100c: 000050f0 streqd r5, [r0], -r0
Zone data :
$ arm-eabi-objdump -s -j .data exp_arm
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 41
...
2fc0 00000000 00000000 00000000 00000000 ................
...
37f0 00000000 00000000 00000000 00000000 ................
3800 00000000 00000014 00000000 00000000 ................
3810 00000000 00000000 00000000 00000000 ................
...
4040 00000000 00000000 00000000 00000000 ................
4050 0000001e 00000000 00000000 00000000 ................
4060 00000000 00000000 00000000 00000000 ................
...
4070 00000000 00000000 00000000 00000000 ................
...
50e0 00000000 00000000 00000000 00000000 ................
50f0 000003e8 ....
1. En fin de zone text on trouve le binaire correspondant aux déclarations des adresses en zone
data. Repérez les valeurs (attention : ce sont des adresses) associées aux étiquettes ptr a,
ptr b, ptr c et ptr x.
2. Retrouvez les valeurs rangées à ces adresses dans la zone data.
3. Quelle est la traduction de l’instruction ldr r1, ptr a ? Etudiez le codage binaire de cette
instruction et retrouvez-y les différents éléments : le code de ldr, le code des registres r1 et pc
et la valeur du déplacement.
4. Quelle est la traduction de l’instruction ldr r1, [r1] ? Etudiez le codage binaire de cette
instruction et retrouvez-y les différents éléments : le code de ldr, le code des registres r1 et r1
et la valeur du déplacement.
5. Comprendre le déplacement codé dans l’instruction ldr r1, ptr a ?
6. Recommencer le même travail avec l’instruction ldr r2, ptr x ?
Codage des instructions ldr et str : La figure 4.1 donne un sous-ensemble des règles de codage
des instructions ldr et str, suffisant pour traiter les exercices précédents. On peut par exemple coder :
ldr rd, [rn, +/-déplacement] ; le bit U code le signe du déplacement (1 pour +, 0 pour −) et le
bit L vaut 1 pour ldr et 0 pour str.
31 28 27 24 23 22 21 20 19 16 15 12 11 0
cond 0101 U 00 L rn rd deplacement
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 42
2. Si l’adresse de départ est multiple de 4, quelle sera la prochaine adresse multiple de 4 ? (en
déduire la place occupée en pratique).
3. Dessiner la mémoire obtenue pour placer la chaine de caractère ”Bonjour” à partir de l’adresse
0x8080
4. Dessiner la mémoire obtenue pour placer le tableau [0x12345678,0xAABBCCDD,0x0,0x1] à
partir de l’adresse 0xA000 (par exemple avec la convention grand-boutiste).
5. Quelles sont les valeurs du tableau vues par Bob si Bob pense que le tableau a été écrit avec la
convention petit-boutiste) ?
Pour les tableaux à 2 dimensions, c’est presque la même chose, il suffit de voir le tableau comme
un tableau à une dimension de tableaux à une dimension : soit un tableau de lignes, soit un tableau
de colonnes.
1. Dessiner la mémoire obtenue pour placer le tableau ci dessous comme tableau de lignes
2. Dessiner la mémoire obtenue pour placer le tableau ci dessous comme tableau de colonnes
3. Dans un tableau d’entiers (32 bits) de 100 lignes et 1000 colonnes quelle sera la distance (en
nombre d’octets) entre 2 éléments voisins sur une même ligne si la tableau a été placé en
mémoire en utilisant la disposition ”tableau de lignes”.
4. Même question pour la disposition ”tableau de colonnes”.
5. Idem pour 2 entiers voisins dans une même colonne pour les deux dispositions.
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 43
Chapitre 5
Exercices :
1. Comprendre l’évolution du contrôle (compteur de programme, valeur des codes de conditions
arithmétiques) pour chacune des deux solutions.
2. Quel est l’effet du programme suivant :
CMP r0, r1
BNE sinon
SUB r2, r0, r1
sinon: ADD r2, r0, r1
3. Coder en langage d’assemblage ARM l’algorithme suivant :
si x est pair alors x <-- x div 2 sinon x <-- 3 * x + 1
la valeur de la variable x étant rangée dans le registre r5.
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 44
5.2 Notion de tableau et accès aux éléments d’un tableau
Considérons la déclaration de tableau suivante :
TAB : un tableau de 5 entiers représentés sur 32 bits.
Il s’agit d’un ensemble d’entiers stockés dans une zone de mémoire contiguë de taille 5 × 32 bits (ou
5 × 4 octets). La déclaration en langage d’assemblage d’une telle zone pourrait être :
debutTAB: .skip 5*4
où debutTAB représente l’adresse du premier élément du tableau (considéré comme l’élément numéro
0). debutTAB est aussi appelée adresse de début du tableau.
Quelle est l’adresse du 2eme élément de ce tableau ? du 3eme ? du ieme , 0 ≤ i ≤ 4 ?
On s’intéresse à l’algorithme suivant :
TAB[0] <-- 11
TAB[1] <-- 22
TAB[2] <-- 33
TAB[3] <-- 44
TAB[4] <-- 55
.data
debutTAB: .skip 5*4
.text
.global main
main:
ldr r0, ptr_debutTAB
mov r1, #11
str r1, [r0]
@ a completer
A la place des lignes marquées (*) on peut écrire une des deux solutions suivantes :
— str r1, [r0, #4] ; le registre r0 n’est alors pas modifié.
— ou mov r2, #4 puis str r1, [r0, r2] ; le registre r0 n’est pas modifié.
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 45
lexique local :
i : un entier compris entre 0 et 4
val : un entier
algorithme :
val <-- 11
i parcourant 0..4
TAB[i] <- val
val <- val + 11
ce qui peut aussi s’écrire :
val <-- 11
i <-- 0
tant que i <> 5 @ ou bien : tant que i <= 4 ou encore i < 5
TAB[i] <- val
val <- val + 11
i <-- i + 1
A noter : si i était mal intialisé avant le tant que (par exemple i = 6), on obtiendrait une boucle
infinie avec le test 6=, et une terminaison sans exécuter le corps du tant que avec les conditions < ou ≤.
Nous exprimons le même algorithme en faisant apparaı̂tre explicitement l’adresse d’accès au mot
de la mémoire : TAB[i].
val <-- 11
i <-- 0
tant que i <> 5
MEM [debutTAB + 4*i] <-- val
val <- val + 11
i <-- i + 1
Exercices :
1. Coder cet algorithme en langage d’assemblage, en installant les variables val, i et debutTAB
respectivement dans les registres : r3, r2 et r0.
Pour évaluer l’expression booléenne i <> 5, on calcule i-5, ce qui nous permet de tester la
valeur de i <> 5 en utilisant l’indicateur Z code de condition arithmétique : si Z = 1, i-5 est
égal à 0 et si Z = 0, i-5 est différent de 0.
2. Dérouler l’exécution en donnant le contenu des registres à chaque itération.
3. Modifier le programme si le tableau est un tableau de mots de 16 bits ?
4. Lors de l’exécution du programme précédent on constate que la valeur contenue dans le registre
r0 reste la même durant tout le déroulement de l’exécution ; il s’agit d’un calcul constant de
la boucle. On va chercher à l’extraire de façon à ne pas le refaire à chaque fois. Pour cela on
introduit une variable AdElt qui contient à chaque itération l’adresse de l’élément accédé.
val <-- 11; i <-- 0
AdElt <- debutTAB
tant que i <= 4
{ invariant : AdElt = debutTAB + 4 * i }
MEM [AdElt] <-- val
i <-- i + 1
val <- val + 11
AdElt <- AdElt + 4
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 46
On peut alors supprimer la variable d’itération i en modifiant le test d’arrêt de l’itération.
D’une boucle de parcours de tableau par indice on passe à une boucle de parcours par pointeur
(la variable indice i peut être supprimée) :
— multiplication des deux membres de l’inéquation par 4 : 4 ∗ i ≤ 4 ∗ 4
— ajout de debutTAB : debutT AB + 4 ∗ i ≤ debutT AB + 4 ∗ 4
— remplacement de debutTAB+4*i par AdElt
{ i = 0 }
val <-- 11; AdElt <- debutTAB; finTAB <- debutTAB+4*4
tant que AdElt <= finTAB
{ invariant : AdElt = debutTAB + 4 * i }
MEM [AdElt] <-- val
val <- val + 11
AdElt <- AdElt + 4
Remarques :
— On peut aussi utiliser les conditions AdElt 6= f inT AB ou AdElt < f inT AB avec
f inT AB < −debutT AB + 4 ∗ 5, en transformant la condtion de départ i 6= 5 ou i < 5.
— dans le corps du tant que, d’après l’invariant, on pourrait recalculer i à partir de AdElt
(i = (AdElt − debutT AB)/4).
Après avoir compris chacune de ces transformations, traduire la dernière version de l’algorithme
en langage d’assemblage.
lexique :
x : un entier naturel
algorithme :
tant que x <> 1
si x est pair
alors x <-- x div 2
sinon x <-- 3 * x + 1
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 47
Chapitre 6
Le schéma standard d’un programme P appelant une fonction ou procédure Q peut s’écrire :
Le premier paramètre c est un code ASCII de lettre minuscule 2 , ainsi que le résultat. Le deuxième
paramètre n est un entier naturel : 0 ≤ n ≤ 26.
Les deux routines ont la même structure de code ci-dessous, seule la manière de transmettre le
résultat à l’appelante change. La traduction de la procédure coderproc peut être traitée dans ce TD
ou reportée au TD 9 après le cours présentant les paramètres de type adresse.
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 48
codefonc: @ prologue (sauvegarder) codeproc: @ prologue (sauvegarder)
code: ... @ code: ... @
... @ code de corps commun ... @ code de corps commun
edoc: @ edoc: @
@ traiter résultat (fonc) @ traiter résultat (proc)
@ épilogue (restaurer) @ épilogue (restaurer)
@ branchement retour @ branchement retour
Le corps des routines est habituellement encadré par une séquence (laissée vide dans cette première
partie de td) de sauvegarde en mémoire (prologue) et de restauration (épilogue) des registres modifiés
dans le corps de la routine. Le branchement de retour à l’appelante termine l’épilogue.
A noter : copier le contenu de cdec dans une variable res stockée en mémoire (section data ou bss 3 )
nécessite 2 instructions ARM :
1 ldr r3,ptr_res @ r3 = adresse de res (&res en C)
2 strb r12,[r3] @ Mem[r3] = cdec (*r3 = cdec en C)
3 ...
4 ptr_res: .word res
L’instruction strb d’écriture en mémoire à l’adresse de res appartiendra soit au code de l’appelante
de la fonction, soit au code de la procédure.
3. Bss : section analogue à data, mais dans laquelle tous les octets seront nuls (pas de valeur initiale). Sert principa-
lement à réduire la taille des fichiers exécutables.
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 49
Dans le code ci-dessous :
— Considérer le type char comme un entier relatif sur 8 bits
— Pres est de type char * : pres contient une adresse de variable de type char où stocker le
résultat
// L’appelée n’écrit pas // L’appelée écrit
// Convention d’appel : // Convention d’appel :
// c : r0, n : r1, // c : r0, n : r1
// valeur de retour : r2 // pres : r2
char coderfonc (char c, unsigned n) { char coderfonc (char c, unsigned n, char *pres) {
char cdec; // stockée dans r12 char cdec; // stockée dans r12
cdec = ascii_c + n; cdec = ascii_c + n;
if (cdec > ’z’) { if (cdec > ’z’) {
cdec = cdec - 26; cdec = cdec - 26;
} }
return cdec; *pres= cdec; // Mem[pres] = cdec
// valeur retournée dans r2 // Résultat dans Mem[r2]
} }
Voici un squelette de code d’appel dans l’appelante pour les deux versions de routine. Il est
instancié 2 fois (pour x=1 avec c ← ’b’ et n ← 4, et pour x=2 avec c ← lu et n ← 2) :
Quelle(s) instruction(s) faut-il mettre dans le bloc branchement retour des routines. Pourquoi
ne peut-on pas utiliser un branchement ordinaire à une étiquette (b resfonc) ?
Traduire côte à côte (et comparer) en code ARM pour les deux versions de routine :
1. le passage des paramètres explicites dans le code de main (blocs parfonc et parproc)
4. pour la procédure : le code traiter résultat de coderproc (le bloc resproc est vide)
Une instruction machine et le circuit matériel de multiplication sont devenus courants sur les
processeurs RISC modernes, mais leur présence constituait l’exception plutôt que la norme sur les
processeurs RISC de première génération. Le code de calcul de n ! ci-dessous illustre l’appel d’une
fonction mult de calcul du produit. Les variables n, res et i sont de type entier naturel.
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 50
// Code de calcul de n! // Prototype de la fonction mult
res=1; // et convention d’appel
i = n; // x : registre r0 y : registre r1
while (i != 1) { // Valeur de retour :
res = mult(res,i); // res = res * i // registre r0 (remplace x)
i = i-1; // Tous entiers naturels 32 bits
} uint32_t mult (uint32_t x, uint32_t y);
Vous trouverez une réalisation de mult en annexe mais vous n’avez pas besoin d’en comprendre le
fonctionnement pour faire l’exercice.
Le code est complété pour calculer factx = x !, x et factx étant des variables stockées en mémoire.
Traduire les affectations n=x et factx=res.
@restaurations omises
b exit @ à améliorer
// EcrNdecimal32(factx);
} px: .word x
pfactx: .word fcatx
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 51
6.3.3 Deux niveaux d’appel avec fonction fact
Le bloc calcul est transformé en une fonction fact avec convention d’appel :
1. Paramètre n dans registre r7
2. Valeur de retour dans registre r5
// EcrNdecimal32(factx); @ EcrNDecimal32(factx)
} mov pc,lr
Indiquer à quels endroits le registre lr doit être sauvegardé puis restauré pour que l’exécution du
programme n’entre pas dans une boucle infinie.
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 52
// Type des procédures d’entrées/sorties :
void LireCar (char *destination); // Mem[destination] = caractère lu au clavier
void EcrCar (char a_ecrire); // Affiche a_ecrire à l’écran
.text
main:
@ LireCar(&lu)
... @ A COMPLETER
bl Lirecar
@ le caractère lu est dans la zone data à l’adresse lu
.
@ EcrCar(res2) : le caractère à écrire doit ^
etre dans r1
... @ A COMPLETER
bl EcrCar
......
ptr_lu: .word lu
ptr_res2: .word res2
Compléter la traduction des appels à LireCar et Ecrcar dans la première partie du TD.
Traduire les appels aux routines de lecture et écriture dans le code fonction de main qui appelle
fact.
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 53
Chapitre 7
TD séance 8 : Appels/retours de
procédures, action sur la pile
La pile est une zone de la mémoire. Elle est accessible par un registre particulier appelé pointeur
de pile (noté sp, pour stack pointer) : le registre sp contient une adresse qui repère un mot de la
zone mémoire en question.
— empiler : on range une information (en général le contenu d’un registre) au sommet de la pile.
— dépiler : on ”prend” le mot en sommet de pile pour le ranger par exemple dans un registre.
Le tableau ci-dessous décrit les différentes façons de mettre en oeuvre une pile en fonction des
conventions possibles pour le sens de progression (vers les adresses croissantes ou décroissantes) et
pour la contenu de la case mémoire pointée (vide ou pleine).
Dans le TD et dans tout le semestre, on travaille avec un type de mise en oeuvre. On choisit celle qui
est utilisée dans le compilateur arm-eabi-gcc c’est-à-dire ”décroissant, dernier plein” (Cf. figure 7.1).
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 54
Mem Mem
0 0
sommet de pile
après
avant
SP
SP
max max
empiler
Figure 7.1 – Mise en oeuvre de la pile. La pile progresse vers les adresses décroissantes, le pointeur de
pile repère la dernière information empilée
Questions :
— Quelle est la valeur de sp quand la pile est pleine ?
— De combien de mots de 32 bits dispose-t-on dans la pile ?
— De combien d’octets dispose-t-on dans la pile ?
— Ecrire en ARM les deux instructions permettant d’empiler le contenu d’un octet du registre
r0. Dans la suite du TD on ecrira : empiler r0.
— Ecrire en ARM les deux instructions permettant de depiler le sommet de pile dans le registre
r0. Dans la suite du TD on ecrira : depiler r0.
— Dessiner l’état de la mémoire après chacune des étapes du programme suivant : mov r0,#
7; empiler r0; mov r0, # 2; empiler r0; mov r0, # 5; empiler r0; mov r0, # 47;
depiler r0; depiler r0; mov r0, # 9; empiler r0
— Reprendre l’exercice si on travaille avec des informations codées sur 4 octets. Comment modifier
le code de empiler et depiler ?
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 55
Remarque : il s’agit du programme donné en cours dans lequel on a remplacé les Ai, Bi et Ci par
des vraies instructions.
10 A1= mov r0, # 0 60 B1= empiler r0 80 C1= mov r0, # 47
14 A2= empiler r0 68 B2= add r0, r0, # 1 84 bl 60 (B)
1c bl 60 (B) 6c B3= depiler r0 88 C2= empiler r0
20 A3= mov r5, #28 74 mov pc, lr 90 bl si condX 80 (C)
24 bl 80 (C) 94 C3= mov r2, r5
28 A4= depiler r0 98 C4= depiler r0
a0 mov pc, lr
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 56
Chapitre 8
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 57
Chapitre 9
Exercices :
— transformer la traduction de ces fonctions en langage ARM pour gérer le passage des paramètres
et les variables locales dans la pile. Écrire les appels qui correspondent.
— reprendre les exemples traités précédemment dans ce TD et effectuer les sauvegardes nécessaires
de temporaires dans la pile.
Reprendre cette traduction en supposant que les 3 paramètres explicites sont à présent passés
dans la pile (paramètre de gauche c en sommet de pile). On pourra si nécessaire passer par une
première version dans laquelle les paramètres sont dans data ou bss.
n, fn : entier
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 58
Lire (n)
fact2 (n, adresse de fn)
Ecrire (fn)
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 59
Chapitre 10
Nous le compilons sans optimisations (option -O0) et produisons le code en langage d’assemblage
ARM (option -S) avec la commande suivante : arm-aebi-gcc -O0 -S premier.c. Le code en langage
d’assemblage est produit dans le fichier premier.s (Cf. Annexe 10.5).
Questions :
1. Le premier appel à la fonction printf a 2 paramètres : une chaı̂ne de caractères et un entier.
Ces paramètres sont passés dans des registres, lesquels ?
2. Observez maintenant l’appel à la fonction fgets. Retrouvez ses paramètres dans le code.
3. La fonction strlen a un paramètre et un résultat. Où sont rangées ces informations dans le
code ?
4. Déduire du code la convention utilisée par le compilateur pour le passage des paramètres et le
retour des résultats de fonctions.
5. Quel est l’effet des 3 premières instructions du code assembleur de main ?
6. Quel est l’effet des 3 dernières instructions du code assembleur de main ?
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 60
10.2 Programme avec une procédure qui a beaucoup de paramètres
Considérons le programme bcp param.c écrit en langage C suivant :
1 include "stdio.h"
2
3 static long int Somme (long int a1, long int a2, long int a3, long int a4, long int a5,
4 long int a6, long int a7, long int a8, long int a9, long int a10) {
5 long int x1,x2,x3,x4,x5,x6,x7,x8,x9,x10;
6 long int y;
7
8 x1=a1+1; x2=a2+1; x3=a3+1; x4=a4+1; x5=a5+1;
9 x6=a6+1; x7=a7+1; x8=a8+1; x9=a9+1; x10=a10+1;
10 y = x1+x2+x3+x4+x5+x6+x7+x8+x9+x10;
11 return (y);
12 }
13
14 int main () {
15 long int z;
16
17 z = Somme (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
18 printf("La somme des entiers de 1 a 10 plus 10 vaut %d\n", z);
19 }
Le code produit dans le fichier bcp param.s par la commande : arm-aebi-gcc -O0 -S
bcp param.c est dans le paragraphe 10.6.
Questions :
1. Observez le code du main. Etudier le contenu de la pile avant l’appel bl Somme. Comment sont
passés les paramètres à la fonction Somme ?
2. Où est rangé le résultat rendu par la fonction Somme ?
3. Où est rangée la variable locale z ?
4. Observez le code de la fonction Somme. Dessiner la pile et retrouvez comment sont récupérés les
paramètres. Où sont rangées les variables locales : x1,x2,x3,x4,x5,x6,x7,x8,x9,x10 et y ?
1 #include "stdio.h"
2
3 #define N 100
4
5 short int Compare2Chaines (char *s1, char *s2) {
6 char *p1, *p2 ;
7
8 p1 = s1 ; p2 = s2 ;
9 while ( *p1 && *p2 && (*p1 == *p2) ) {
10 p1++ ; p2++ ;
11 }
12 return (*p1 == 0) && (*p2 == 0) ;
13 }
14
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 61
15 int main () {
16 short int r ;
17 char chaine1 [N], chaine2[N] ;
18
19 printf("Chaine 1, de moins de 99 caracteres : \n");
20 fgets (chaine1, N, stdin);
21 printf("Chaine 2, de moins de 99 caracteres : \n");
22 fgets (chaine2, N, stdin);
23
24 r = Compare2Chaines (chaine1,chaine2);
25
26 printf("Sont-elles egales ? %s !\n", (r ? "oui" : "non"));
27 }
Le code produit dans le fichier var pile.s par la commande : arm-aebi-gcc -O0 -S var pile.c
est dans le paragraphe 10.7.
Questions :
1. Dans le main le compilateur réserve 208 octets. Comment sont-ils utilisés ?
2. Quels sont les paramètres de la fonction Compare2Chaines ?
3. Observez le code suivant le retour de l’appel à Compare2Chaines. Commentez précisément les
lignes entre mov r3, r0 et mov r1, r3. Quels sont les paramètres passés à la fonction printf
qui suit ?
4. Commentez le code de la fonction Compare2Chaines. Comment est généré le code d’une ins-
truction while ?
1 #include "stdio.h"
2 #define NMax 1000000000
3
4 int main() {
5 int i,j,zero,tab[2]; i=NMax;zero=0;tab[0]=0;tab[1]=0;
6 for(i=NMax;i;i--) {
7 for(j=1;j>=0;j--) {
8 if (i&(1<<j)) {
9 tab[j]++;}
10 if (j==0) {
11 zero++;}}}
12 printf("%d - %d - %d\n",tab[0],tab[1],zero);
13 return;}
La boucle extérieure, sur i, passe en revue tous les entiers entre 1 et Nmax (en sens inverse).
La boucle intérieure, sur j, compte les 0 pour les bits en position j (j=1 puis j=0). Selon la théorie,
deux boucles imbriquées peuvent être réécrites en une seule boucle et parfois cela permet d’éviter des
branchements coûteux ...
— Réécrire le programme en conservant le traitement effectué avec une seule boucle globale.
Conserver la gestion de i et de j (en particulier les lignes à l’intérieur de la boucle interne, i.e.
les lignes 8, 9, 10 et 11, ne doivent pas être modifiées)
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 62
— Réécrire ce programme une seconde fois en déroulant la boucle intérieure, c’est à dire en faisant
disparaı̂tre j.
— Discuter sur le gain en temps susceptible d’être obtenu avec les deux programmes précédents
(pour la réponse effective, attendre le TP)
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 63
49 mov r0, r3
50 bl strlen
51 mov r3, r0
52 str r3, [fp, #-8]
53 ldr r0, .L2+12
54 ldr r1, [fp, #-8]
55 bl printf
56 mov r0, r3
57 sub sp, fp, #4
58 ldmfd sp!, {fp, lr}
59 bx lr
60 .L3:
61 .align 2
62 .L2:
63 .word .LC0
64 .word _impure_ptr
65 .word .LC1
66 .word .LC2
67 .size main, .-main
68 .ident "GCC: (GNU) 4.5.3"
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 64
34 add r3, r3, #1
35 str r3, [fp, #-16]
36 ldr r3, [fp, #-68]
37 add r3, r3, #1
38 str r3, [fp, #-20]
39 ldr r3, [fp, #4]
40 add r3, r3, #1
41 str r3, [fp, #-24]
42 ldr r3, [fp, #8]
43 add r3, r3, #1
44 str r3, [fp, #-28]
45 ldr r3, [fp, #12]
46 add r3, r3, #1
47 str r3, [fp, #-32]
48 ldr r3, [fp, #16]
49 add r3, r3, #1
50 str r3, [fp, #-36]
51 ldr r3, [fp, #20]
52 add r3, r3, #1
53 str r3, [fp, #-40]
54 ldr r3, [fp, #24]
55 add r3, r3, #1
56 str r3, [fp, #-44]
57 ldr r2, [fp, #-8]
58 ldr r3, [fp, #-12]
59 add r2, r2, r3
60 ldr r3, [fp, #-16]
61 add r2, r2, r3
62 ldr r3, [fp, #-20]
63 add r2, r2, r3
64 ldr r3, [fp, #-24]
65 add r2, r2, r3
66 ldr r3, [fp, #-28]
67 add r2, r2, r3
68 ldr r3, [fp, #-32]
69 add r2, r2, r3
70 ldr r3, [fp, #-36]
71 add r2, r2, r3
72 ldr r3, [fp, #-40]
73 add r2, r2, r3
74 ldr r3, [fp, #-44]
75 add r3, r2, r3
76 str r3, [fp, #-48]
77 ldr r3, [fp, #-48]
78 mov r0, r3
79 add sp, fp, #0
80 ldmfd sp!, {fp}
81 bx lr
82 .size Somme, .-Somme
83 .section .rodata
84 .align 2
85 .LC0:
86 .ascii "La somme des entiers de 1 a 10 plus 10 vaut %d\012\000"
87 .text
88 .align 2
89 .global main
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 65
90 .type main, %function
91 main:
92 @ Function supports interworking.
93 @ args = 0, pretend = 0, frame = 8
94 @ frame_needed = 1, uses_anonymous_args = 0
95 stmfd sp!, {fp, lr}
96 add fp, sp, #4
97 sub sp, sp, #32
98 mov r3, #5
99 str r3, [sp, #0]
100 mov r3, #6
101 str r3, [sp, #4]
102 mov r3, #7
103 str r3, [sp, #8]
104 mov r3, #8
105 str r3, [sp, #12]
106 mov r3, #9
107 str r3, [sp, #16]
108 mov r3, #10
109 str r3, [sp, #20]
110 mov r0, #1
111 mov r1, #2
112 mov r2, #3
113 mov r3, #4
114 bl Somme
115 str r0, [fp, #-8]
116 ldr r0, .L3
117 ldr r1, [fp, #-8]
118 bl printf
119 mov r0, r3
120 sub sp, fp, #4
121 ldmfd sp!, {fp, lr}
122 bx lr
123 .L4:
124 .align 2
125 .L3:
126 .word .LC0
127 .size main, .-main
128 .ident "GCC: (GNU) 4.5.3"
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 66
15 .type Compare2Chaines, %function
16 Compare2Chaines:
17 @ Function supports interworking.
18 @ args = 0, pretend = 0, frame = 16
19 @ frame_needed = 1, uses_anonymous_args = 0
20 @ link register save eliminated.
21 str fp, [sp, #-4]!
22 add fp, sp, #0
23 sub sp, sp, #20
24 str r0, [fp, #-16]
25 str r1, [fp, #-20]
26 ldr r3, [fp, #-16]
27 str r3, [fp, #-8]
28 ldr r3, [fp, #-20]
29 str r3, [fp, #-12]
30 b .L2
31 .L4:
32 ldr r3, [fp, #-8]
33 add r3, r3, #1
34 str r3, [fp, #-8]
35 ldr r3, [fp, #-12]
36 add r3, r3, #1
37 str r3, [fp, #-12]
38 .L2:
39 ldr r3, [fp, #-8]
40 ldrb r3, [r3, #0] @ zero_extendqisi2
41 cmp r3, #0
42 beq .L3
43 ldr r3, [fp, #-12]
44 ldrb r3, [r3, #0] @ zero_extendqisi2
45 cmp r3, #0
46 beq .L3
47 ldr r3, [fp, #-8]
48 ldrb r2, [r3, #0] @ zero_extendqisi2
49 ldr r3, [fp, #-12]
50 ldrb r3, [r3, #0] @ zero_extendqisi2
51 cmp r2, r3
52 beq .L4
53 .L3:
54 ldr r3, [fp, #-8]
55 ldrb r3, [r3, #0] @ zero_extendqisi2
56 cmp r3, #0
57 bne .L5
58 ldr r3, [fp, #-12]
59 ldrb r3, [r3, #0] @ zero_extendqisi2
60 cmp r3, #0
61 bne .L5
62 mov r3, #1
63 b .L6
64 .L5:
65 mov r3, #0
66 .L6:
67 mov r3, r3, asl #16
68 mov r3, r3, lsr #16
69 mov r3, r3, asl #16
70 mov r3, r3, asr #16
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 67
71 mov r0, r3
72 add sp, fp, #0
73 ldmfd sp!, {fp}
74 bx lr
75 .size Compare2Chaines, .-Compare2Chaines
76 .section .rodata
77 .align 2
78 .LC0:
79 .ascii "Chaine 1, de moins de 99 caracteres : \000"
80 .align 2
81 .LC1:
82 .ascii "Chaine 2, de moins de 99 caracteres : \000"
83 .align 2
84 .LC2:
85 .ascii "oui\000"
86 .align 2
87 .LC3:
88 .ascii "non\000"
89 .align 2
90 .LC4:
91 .ascii "Sont-elles egales ? %s !\012\000"
92 .text
93 .align 2
94 .global main
95 .type main, %function
96 main:
97 @ Function supports interworking.
98 @ args = 0, pretend = 0, frame = 208
99 @ frame_needed = 1, uses_anonymous_args = 0
100 stmfd sp!, {fp, lr}
101 add fp, sp, #4
102 sub sp, sp, #208
103 ldr r0, .L10
104 bl puts
105 ldr r3, .L10+4
106 ldr r3, [r3, #0]
107 ldr r3, [r3, #4]
108 sub r2, fp, #108
109 mov r0, r2
110 mov r1, #100
111 mov r2, r3
112 bl fgets
113 ldr r0, .L10+8
114 bl puts
115 ldr r3, .L10+4
116 ldr r3, [r3, #0]
117 ldr r3, [r3, #4]
118 sub r2, fp, #208
119 mov r0, r2
120 mov r1, #100
121 mov r2, r3
122 bl fgets
123 sub r2, fp, #108
124 sub r3, fp, #208
125 mov r0, r2
126 mov r1, r3
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 68
127 bl Compare2Chaines
128 mov r3, r0
129 strh r3, [fp, #-6] @ movhi
130 ldrsh r3, [fp, #-6]
131 cmp r3, #0
132 beq .L8
133 ldr r3, .L10+12
134 b .L9
135 .L8:
136 ldr r3, .L10+16
137 .L9:
138 ldr r0, .L10+20
139 mov r1, r3
140 bl printf
141 mov r0, r3
142 sub sp, fp, #4
143 ldmfd sp!, {fp, lr}
144 bx lr
145 .L11:
146 .align 2
147 .L10:
148 .word .LC0
149 .word _impure_ptr
150 .word .LC1
151 .word .LC2
152 .word .LC3
153 .word .LC4
154 .size main, .-main
155 .ident "GCC: (GNU) 4.5.3"
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 69
Chapitre 11
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 70
instruction signification code opération taille codage
(valeurs en décimal)
load# vi acc <-- vi 1 2 mots
input acc <-- Mem[0xFE] 2 1 mot
output Mem[0xFF] <-- acc 4 1 mot
push-acc empiler acc 8 1 mot
pop-acc dépiler vers acc 16 1 mot
add ajouter le sommet et le sous-sommet 32 1 mot
de la pile, ils sont dépilés,
empiler la somme
l’accumulateur n’est pas modifié
dup dupliquer le sommet de pile 64 1 mot
jumpifAccnul depl saut conditionnel à pc+depl 128 2 mot
la condition est ”accumulateur nul”
MEM
0x00
PROCESSEUR programme
adresse mémoire
PC
MA
sp
Rinst
ACC mk1
pile
mk2 0xFD
0xFE interface
0xFF
donnée mémoire
MB
écran
clavier
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 71
11.1.1 Représentation en mémoire d’un programme
Donner la représentation en mémoire (en binaire et en hexadécimal) du programme en langage
d’assemblage suivant :
load# 3
push-acc
push-acc
add
pop-acc
11.2.1 Algorithme
Donner l’algorithme d’interprétation des instructions.
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 72
BusAd
ma
0 0xfe 0xff
Egal 0 ? oui/non
busA
op1
UAL
acc pc sp mk1 mk2 res
busB
op2
busC
BusDon
mb
opérations UAL
res=op1
res=op1 + 1
res=op1 − 1 Rinst compare 1,2,4,... oui/non
res=op1 + op2
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 73
2. micro-actions permettant l’accès à la mémoire :
— lecture mémoire : mb ← Mem [ma]
— écriture mémoire : Mem [ma] ← mb
avec reg i, reg j, reg k ∈ { sp, pc, mk1, mk2, acc }.
On dispose des tests de la valeur contenue dans le registre Rinst : Rinst = code de load#, code
de add, etc.
Par ailleurs, le “calcul” acc = acc + 0 permet de tester si acc est nul où non.
load# -1
push
dup
load# 4
push
TITI: add
pop
dup
push
jumpifAccnul TOTO
load# 0
jumpifAccnul TITI
TOTO: load# 5a
output
11.4.1 Questions
1. Donner le code en hexadécimal ainsi que son implantation en mémoire à partir de l’adresse 0.
La question intéressante est la valeur du déplacement pour les instructions de branchements.
2. Donner l’évolution des valeurs dans les registres et dans la pile lors de l’exécution de ce pro-
gramme.
3. Donner la trace en terme d’états du graphe de contrôle du processeur lors de l’exécution de ce
programme.
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 74
11.5.1 Temps de calcul d’une instruction
Une micro-action dure le temps d’une période d’horloge. Choisir une fréquence et calculer le temps
de calcul de chaque instruction du processeur étudié pour le graphe de contrôle proposé dans le
paragraphe 11.3.2.
Pouvez-vous améliorer ce temps de calcul ? Quelles sont les parties incompressibles ?
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 75
Troisième partie
Travaux Pratiques
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 76
Chapitre 1
#define image_width 16
#define image_height 16
static unsigned char image_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 77
Tous les points de cette image doivent être blancs, excepté ceux de la première ligne qui doit
avoir l’aspect suivant :
— Utilisez le programme bitmap pour afficher l’image contenue dans le fichier monimage.bm.
Vérifiez que l’image affichée correspond bien au résultat attendu.
— Ecrivez en binaire les valeurs que vous avez codées dans le fichier. Expliquez le codage que vous
avez utilisé pour obtenir l’image demandée.
/* prog.c */
int NN = 0xffff;
char CC[8] = "charlot";
int main() {
NN = 333;
NN= NN + 5;
}
Vous allez le compiler, c’est-à-dire le traduire dans un langage interprétable par une machine avec
la commande : arm-eabi-gcc -c prog.c. Vous obtenez le fichier prog.o.
C’est du “binaire”... Nous allons le regarder avec différents outils.
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 78
1.2.3 Affichage plus “lisible”
Le programme a été traduit dans le langage machine ARM.
La commande arm-eabi-objdump -S prog.o donne la séquence d’instructions ARM qui correspond
à nos instructions C. On peut lire l’adresse de l’instruction, puis son code en hexadécimal et enfin les
mnémoniques correspondants en langage d’assemblage.
On va repérer le code qui correspond à l’instruction NN = 333. C’est fait en deux fois :
La question suivante étant un peu plus complexe, vous en chercherez la réponse chez vous ou
en fin de séance si vous avez terminé en avance. Pour cela il faut lire en détail le paragraphe 2.3
de la documentation technique et la remarque du paragraphe 2.1.4. Pourquoi le processeur ARM ne
permet-il pas d’écrire mov r3, #333 ?
arm-eabi-gcc traduit un programme écrit dans le langage C en un programme écrit en langage
machine du processeur ARM.
Avec d’autres options le compilateur gcc traduit dans le langage machine d’autres processeurs. Par
exemple, par défaut, gcc effectue la traduction pour le processeur contenu dans la machine sur laquelle
vous travaillez ; dans votre cas c’est le langage machine du processeur INTEL... Effectuez l’expérience
suivante :
gcc -c prog.c
hexdump -C prog.o
objdump -S prog.o
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 79
— Produire les 2 programmes en langage machine : arm-eabi-gcc -c prog1.s et arm-eabi-gcc
-c prog1.var1.s).
— Observer leur contenu : arm-eabi-objdump -S prog1.o et arm-eabi-objdump -S
prog1.var1.o.
— Comment interprétez-vous les résultats de cette expérience ?
Reproduire la même expérience pour les instructions : ADDS r10, r2, #10 (programme
prog1.var2.s) et ADD r10, r2, r3 (programme prog1.var3.s).
Ci-dessous le contenu des fichiers servant à cette expérience.
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 80
Pour plus d’informations vous pouvez regarder :
http://en.wikipedia.org/wiki/RGB color model
La figure 1.1 donne la description d’une image dans le format xpm. Cette image comporte deux
segments. L’image est décrite dans le langage C à l’aide d’un tableau de caractères. On y trouve la
taille de l’image (32 × 32), le nombre de caractères utilisés pour la représenter (3), la couleur (au
codage RGB) associée à chacun des caractères, et enfin la matrice de points, un caractère étant associé
à un point. None désigne une couleur prédéfinie dans le système.
On remarque que la proportion d’une couleur est codée sur deux chiffres hexadécimaux, ff
représentant le maximum.
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 81
/* XPM */
static char *lignes[]={ /* le fichier doit s’appeler lignes.xpm */
"32 32 3 1",
". c None",
"# c #f0f000",
"a c #ff0000",
"................................",
"................................",
"................................",
"................................",
"................................",
"................................",
"...############.................",
"................................",
"................................",
"................................",
"..................a.............",
"..................a.............",
"..................a.............",
"..................a.............",
"..................a.............",
"..................a.............",
"..................a.............",
"..................a.............",
"..................a.............",
"..................a.............",
"................................",
"................................",
"................................",
"................................",
"................................",
"................................",
"................................",
"................................",
"................................",
"................................",
"................................",
"................................"};
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 82
Chapitre 2
2.1.2 Addition
Poser en décimal sur 3 chiffres, en hexadécimal sur 2 chiffres et en binaire sur 8 bits l’addition
5710 + 0xa3. Sur l’opération binaire :
1. faire apparaı̂tre les retenues ci , la dernière retenue C = c8
2. les deux dernières retenues sont-elles égales ?
3. que valent les indicateurs N, Z et V ?
4. que valent les opérandes et le résultat apparent sur 8 bits et l’opération est-elle correcte ?
— s’il s’agit d’entiers naturels
— s’il s’agit d’entiers relatifs
Quelles réponses changent si cette même addition est réalisée sur 9 bits ?
2.1.3 Soustraction
Poser en décimal sur 2 chiffres, en hexadécimal sur 1 chiffre et en binaire sur 4 bits les soustractions
suivantes : 0xc - 0x8, 0x8 - 0xc, 0x7 - 0x7. Sur l’opération binaire sur 4, puis sur 5 bits en observant
les changements :
1. faire apparaı̂tre les emprunts ei et le dernier emprunt E=e5 (puis e6 )
2. que valent les indicateurs N, Z et V ?
3. interpréter l’opération en supposant qu’il s’agisse d’entier naturels, puis d’entiers relatifs
4. la soustraction est-elle possible dans l’ensemble N ?
5. la soustraction donne-t-elle un résultat correct dans l’ensemble Z ?
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 83
2.1.4 Soustraction par addition du complément à 2
Poser en binaire sur 4 puis sur 5 bits l’addition 0xc + 0x7 en utilisant une retenue initiale non
nulle (c0 = 1). Comparer la ligne des retenues (dont C) avec celles des emprunts (dont E) de la
soustraction précédente 0xc-0x8.
Quelle doit être la valeur de C pour que la soustraction dans N soit possible ?
Syntaxe d’utilisation
La syntaxe d’utilisation de la calculette est la suivante :
A titre d’exemple, voici plusieurs manières de spécifier l’entier 1111000010012 sur 12 bits :
1. en binaire : 0b111100001001 /0b000011110110 ou −0b000011110111
2. en hexadécimal : 0xf09 /0x0f6 ou −0x0f7
3. et en décimal : 3849 /246 ou −247.
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 84
2. écriture binaire du résultat apparent Σ, et valeurs décimales en tant qu’entier naturel et relatif
3. bit de poids forts N = Σn−1 , an−1 et bn−1 .
4. indicateur V, dernière C = cn et avant-dernière cn−1 retenue
5. le résultat apparent Σ est-il correct pour des entiers relatifs, pour des entiers naturels
Effectuer sur 5 bits les additions de relatifs +4 + +5 et -8 +-8. Comparer aux mêmes addition sur
4 bits. Que peut-on dire de N lorsque le résultat apparent d’une addition d’entiers relatifs est incorrect ?
Expliquer pourquoi après avoir effectué le calcul a-b sur des entiers relatifs, la condition a < b
s’écrit N etV ouN etV 2
Expliquer pourquoi après avoir effectué le calcul a-b sur des entiers naturels, la condition a < b
s’écrit C
Effectuer sur 8 bits entre les opérandes 0xcc et 0x55 les opérations suivantes : or, and, xor.
Expliquer le résultat obtenu
Effectuer sur 12 bits les opérations suivantes entre les opérandes 0x1f5 et 3, puis 0x842 et 2 :
1. lsl (Logic Shift Left)
2. lsr (Logic Shift Right)
3. asr (Arithmetic Shift Right)
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 85
Chapitre 3
aa : le caractère ’A’
oo : l’entier 15 sur 8 bits (1 octet)
cc : la chaine "bonjour"
rr : <’B’, 3> de type <un caractère, un entier sur 1octet>
T : le tableau d’entiers sur 16 bits [0x1122, 0x3456, 0xfafd]
xx : l’entier 65 sur 8 bits (1 octet)
On le traduit en langage d’assemblage ARM. Le fichier donnees.s contient une zone data dans
laquelle sont déclarées les données correspondant aux déclarations ci-dessus.
La directive .byte (respectivement .hword, .word) permet de déclarer une valeur exprimée sur
8 bits (respectivement 16, 32 bits). Une valeur peut être écrite en décimal (65) ou en hexadécimal
(0x41).
Pour déclarer une chaı̂ne, on peut utiliser la directive .asciz et des guillemets.
Le caractère @ marque le début d’un commentaire, celui-ci se poursuivant jusqu’à la fin de la ligne.
.data
aa: .byte 65 @ .byte 0x41
oo: .byte 15 @ .byte 0x0f
cc: .asciz "bonjour"
rr: .byte 66 @ .byte 0x42
.byte 3
T: .hword 0x1122
.hword 0x3456
.hword 0xfafd
xx: .byte 65
Nous allons maintenant observer le codage en mémoire de cette zone data. Traduire le programme
donnees.s en binaire avec la commande :
arm-eabi-gcc -c -mbig-endian donnees.s.
Notez que nous utilisons l’option -mbig-endian dans le but de faciliter la lecture (rangement par
“grands bouts”). Vous pourrez en observer le fonctionnement dans la partie 3.4.2. Vous obtenez le
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 86
fichier donnees.o. Observez le contenu de ce fichier :
arm-eabi-objdump -j .data -s donnees.o
Chaque ligne comporte une adresse puis un certain nombre d’octets et enfin leur correspondance
sous forme d’un caractère (quand cela a un sens). Dans quelle base les informations sont-elles affichées ?
Combien d’octets sont-ils représentés sur chaque ligne ? Donnez pour chacun des octets affichés la
correspondance avec les valeurs déclarées dans la zone data. Comment est codée la chaı̂ne de caractères,
en particulier comment est représentée la fin de cette chaı̂ne ?
Nous voulons maintenant représenter tous les entiers sur 32 bits ; d’où le nouveau lexique :
aa : le caractère ’A’
oo : l’entier 15 sur 32 bits
cc : la chaine "bonjour"
rr : <’B’, 3> de type <un caractère, un entier sur 32 bits>
T : le tableau d’entiers sur 32 bits [0x1122, 0x3456, 0xfafd]
xx : l’entier 65 sur 32 bits
La directive de déclaration pour définir une valeur sur 32 bits est .word.
Copiez le fichier donnees.s dans donnees2.s et modifiez donnees2.s. Compilez donnees2.s.
Quelle est maintenant la représentation de chacun des entiers de la zone data modifiée ?
@ accesmem.s
.data
aa: .word 24
xx: .word 266
bb: .word 42
.text
.global main
main:
LDR r5, ptr_xx
LDR r6, [r5]
@ impression du contenu de r5
MOV r1, r5
BL EcrHexa32
@ impression du contenu de r6
MOV r1, r6
BL EcrHexa32
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 87
ptr_xx: .word xx
Ce programme utilise une fonction d’affichage EcrHexa32 qui est définie dans un autre module es.s
(Cf. chapitre 4). Cette fonction affiche à l’écran en hexadécimal la valeur contenue dans le registre r1
obligatoirement.
Produisez l’exécutable accesmem :
arm-eabi-gcc -c es.s
arm-eabi-gcc -c accesmem.s
arm-eabi-gcc -o accesmem accesmem.o es.o
Exécutez ce programme : arm-eabi-run accesmem. Notez les valeurs affichées. Que représente
chacune d’elle ?
@ accesmem2.s
.data
D1: .word 266
D2: .hword 42
D3: .byte 12
.text
.global main
main:
LDR r3, ptr_D1
LDR r4, [r3]
ptr_D1: .word D1
ptr_D2: .word D2
ptr_D3: .word D3
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 88
3.2.3 Ecriture en mémoire
L’instruction STR (respectivement STRH, STRB) permet de stocker un mot représenté sur 32 (res-
pectivement 16, 8) bits dans la mémoire.
Le programme ecrmem.s affiche la valeur rangée à l’adresse DW, puis range à cette adresse la
valeur 1048576 ; le mot d’adresse DW est alors lu et affiché. Exécutez ce programme et constatez
qu’effectivement le mot d’adresse DW a été modifié. Modifiez le programme ecrmem.s pour faire le
même genre de travail mais avec un mot de 16 bits rangé à l’adresse DH et un mot de 8 bits rangé à
l’adresse DB.
Remarque : les adresses sont toujours représentées sur 32 bits.
.data
DW: .word 0
DH: .hword 0
DB: .byte 0
.text
.global main
main:
LDR r0, ptr_DW
LDR r1, [r0]
BL EcrNdecimal32
ptr_DW: .word DW
ptr_DH: .word DH
ptr_DB: .word DB
.data
cc: @ ne pas modifier cette partie
.byte 0x42
.byte 0x4f
.byte 0x4e
.byte 0x4a
.byte 0x4f
.byte 0x55
.byte 0x52
.byte 0x00 @ code de fin de chaine
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 89
@ la suite pourra etre modifiee
.word 12
.word 0x11223344
.asciz "au revoir..."
.text
.global main
main:
@ modification de la chaine
@ A COMPLETER
ptr_cc: .word cc
Compilez ce programme et exécutez-le ; vous constatez qu’il affiche deux fois la chaı̂ne de caractères
d’adresse cc.
Modifiez ce programme pour qu’il affiche la chaı̂ne "BONJOUR" sur une ligne puis la chaine "au
revoir..." sur la ligne suivante. Il y a plusieurs façons de traiter cette question, vous pouvez essayer
plusieurs solutions (c’est même conseillé) mais celle qui nous intéresse le plus ici consiste à utiliser
l’indirection avec un pointeur relais. Plus précisément vous devez identifier l’adresse de début de chaque
chaine (avec une étiquette) et utiliser cette étiquette pour réaliser l’affichage souhaité.
La chaı̂ne d’adresse cc est formée de caractères majuscules. Modifiez le programme en ajoutant
une suite d’instructions qui transforme chaque caractère majuscule en minuscule. On peut résoudre
ce problème sans écrire une boucle. Compilez et exécutez votre programme.
Indication : inspirez-vous de l’exercice fait en TD1. L’opération OU peut être réalisée avec l’ins-
truction ORR.
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 90
Le problème vient du fait que les mots de 32 bits doivent être placés à des adresses multiples de
4. De même les entiers représentés sur 2 octets doivent être stockés à des adresses multiples de 2.
Pour rétablir l’alignement insérer la ligne suivante :
.balign 4
juste avant la déclaration de l’entier z, et appelez ce nouveau programme alignements2.s.
Vérifiez que le problème est résolu.
Ecrivez un programme dans lequel vous déclarez une valeur représentée sur 16 bits et dont l’adresse
n’est pas un multiple de 2 (il suffit de placer un octet devant). Reproduisez une expérience similaire à
la précédente (pour rétablir un alignement sur une adresse multiple de 2 utilisez la directive .balign
2).
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 91
Chapitre 4
lexique:
TAB : un tableau de 5 entiers représentés sur 32 bits
algorithme:
TAB[0] <-- 11
TAB[1] <-- 22
TAB[2] <-- 33
TAB[3] <-- 44
TAB[4] <-- 55
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 92
2. target sim
On active le simulateur, ce qui permet d’exécuter des instructions en langage d’assemblage
ARM.
3. load
On charge le programme à exécuter dont on a donné le nom à l’appel de gdb.
4. break main
On met un point d’arrêt juste avant l’étiquette main.
5. run
Le programme s’exécute jusqu’au premier point d’arrêt exclu : ici, l’exécution du programme
est donc arrêtée juste avant la première instruction.
6. list
On voit 10 lignes du fichier source.
7. list
On voit les 10 suivantes.
8. list 10,13
On voit les lignes 10 à 13.
9. info reg
Permet d’afficher en hexadécimal et en décimal les valeurs stockées dans tous les registres.
Notez la valeur de r15 aussi appelé pc, le compteur de programme. Elle représente l’adresse de
la prochaine instruction qui sera exécutée.
10. s
Une instruction est exécutée. gdb affiche une ligne du fichier source qui est la prochaine ins-
truction (et qui n’est donc pas encore exécutée).
11. etc.
Pour l’observation de l’exécution du programme tableau, notez, en particulier, les valeurs suc-
cessives (à chaque itération) de r0, le contenu de la mémoire à partir de l’adresse debutTAB en
début de programme et après l’exécution de toutes les instructions. Sous gdb, pour afficher 5 mots en
hexadécimal, à partir de l’adresse debutTAB, utilisez la commande : x/5w &debutTAB.
val <-- 11
i <-- 0
tant que i <> 5
TAB[i] <- val
i <-- i + 1
val <- val + 11
.data
debutTAB: .skip 5*4
.text
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 93
.global main
main:
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 94
Vous allez traduire cet algorithme en langage d’assemblage et vérifier que son exécution calcule
bien les éléments de la suite de Syracuse.
Quelques indications :
— L’algorithme comporte une itération dans laquelle est incluse une instruction conditionelle.
Vous pouvez traduire chacune des deux constructions en utilisant un des schémas de traduction
précédents. N’hésitez pas à utiliser autant d’étiquettes que vous voulez si cela vous rend le travail
plus lisible.
— Pour tester si un entier est pair il suffit de regarder si son bit de poids faible (le plus à droite)
est égal à 0. Pour cela vous pouvez utiliser une instruction “et logique” avec la valeur 1 ou
l’instruction TST qui exécute la même chose.
— Pour diviser un entier par 2 il suffit de le décaler à droite de 1 position.
— Pour calculer 3 ∗ x on peut calculer 2 ∗ x + x et pour multiplier un entier par 2, il suffit de le
décaler à gauche de 1 position.
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 95
Chapitre 5
TP séances 6 et 7 : Parcours de
tableaux
LEXIQUE :
N_MAX : l’entier 10
Ligne : le type tableau sur [0..N_MAX-1] d’entiers
table : le tableau sur [0..N_MAX-1] de Ligne
n_lig,n_col : deux entiers
ALGORITHME :
pour n_lig parcourant [1..N_MAX] :
pour n_col parcourant [1..N_MAX] :
// produit de n_col par n_lig
table[n_lig-1][n_col-1] <-- n_lig * n_col;
1 2 3 4 5 6 7 8 9 10
2 4 6 8 10 12 14 16 18 20
3 6 9 12 15 18 21 24 27 30
4 8 12 16 20 24 28 32 36 40
5 10 15 20 25 30 35 40 45 50
6 12 18 24 30 36 42 48 54 60
7 14 21 28 35 42 49 56 63 70
8 16 24 32 40 48 56 64 72 80
9 18 27 36 45 54 63 72 81 90
10 20 30 40 50 60 70 80 90 100
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 96
Questions concernant le remplissage du tableau
1. Dans quelle case du tableau table se trouve le produit 1*1 ?
2. Dans quelle case du tableau table se trouve le produit 1*2 ?
3. Dans quelle case du tableau table se trouve le produit 7*9 ?
4. Dans quelle case du tableau table se trouve le produit 10*10 ?
Organisation du travail Dans ce tp, vous avez à écrire une séquence de deux blocs de codes
distincts :
1. le premier initialise (remplit) un tableau en mémoire
2. le second affiche à l’écran le contenu du tableau stocké en mémoire
Il est fortement recommandé de ne tester qu’un bloc de code à la fois : affichage puis remplissage
ou remplissage puis affichage. Les binômes peuvent même effectuer le travail en parallèle et fusionner
les codes ensuite.
LEXIQUE :
N_MAX : l’entier 10
ESPACE : le caractère ’ ’ // code ascii 32
BARRE : le caractère ’|’ // code ascii 124
TIRETS : le caractère ’---’ // code ascii 45
Ligne : le type tableau sur [0..N_MAX-1] d?entiers
table : le tableau sur [0..N_MAX-1] de Ligne
n_lig,n_col : deux entiers
mult : un entier
ALGORITHME :
pour n_lig parcourant [0..N_MAX-1] :
pour n_col parcourant [0..N_MAX-1] :
ecrire_car(BARRE);
mult <-- table[n_lig][n_col];
si mult < 100 alors ecrire_car(ESPACE);
si mult < 10 alors ecrire_car(ESPACE);
ecrire_int(mult);
ecrire_car(BARRE);
a_la_ligne();
répéter N_MAX fois :
ecrire_car(BARRE);
ecrire_chn(TIRETS);
ecrire_car(BARRE);
a_la_ligne();
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 97
Traduire en langage d’assemblage cet algorithme, récupérer le fichier tabmult.s et compléter la
partie affichage. Tester cette partie, pour le tableau évidemment pour l’instant vide ; c’est-à-dire que
l’affichage que vous devez observer est le même que celui de la figure 5.1 mais avec des zéros.
Pour la traduction des fonctions d’entrées-sorties utiliser les fonctions suivantes définies dans le
fichier es.s :
— EcrChn pour implémenter ecrire car et ecrire chn. Pour écrire un caractère sans retour à
la ligne déclarer le caractère comme chaı̂ne.
— EcrNdecim32 pour implémenter ecrire int.
— AlaLigne pour implémenter a la ligne.
LEXIQUE :
mult, a et b : trois entiers positifs ou nuls
ALGORITHME :
mult <-- 0;
répéter a fois : mult <-- mult + b;
questions
1. table étant l’adresse de début du tableau (i.e. du premier élément), exprimer la formule du
donne l’adresse de table[x][y] en fonction de table, x et y ?.
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 98
2. Donner le langage d’assemblage correspondant à la ligne suivante (calcul d’adresse, puis écriture
de la valeur en mémoire) : table[x][y] <-- valeur.
questions
1. Donnez la nouvelle forme de l’algorithme complet.
2. Traduire cette version en langage d’assemblage. Reprenez la version initiale du fichier
tabmult.s, complétez-le avec la traduction de votre algorithme.
3. Compilez votre programme, exécutez le et vérifiez vos résultats . . .
Pour le compte-rendu :
les différentes lignes de vos algorithmes doivent apparaı̂tre de façon claire sous forme de
commentaire dans votre programme en langage d’assemblage. Vous donnerez aussi les
conventions d’implantation des différentes variables dans les registres
5.4 tabmult.s
@ Programme tabmult : Affiche les tables de multiplication de de 1 a 10
N_MAX= 10
.data
barre : .byte ’|’
.byte 0
espace : .byte ’ ’
.byte 0
tirets : .asciz "---"
.text
.global main
main:
@ remplissage du tableau
@ a completer...
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 99
@ affichage du tableau
@ a completer...
BAL exit
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 100
Chapitre 6
TP séances 8, 9 et 10 : Procédures,
fonctions et paramètres
1. Négatif ;
2. Symétries comme dans la figure 6.1 ci-après ;
3. Rotations comme dans la figure 6.1 ci-après.
rot+90 rot−90
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 101
6.2 Négatif d’une image au format bitmap
Le premier objectif de ces TP est de réaliser un programme capable de produire un fichier au
format bitmap qui contienne le négatif de l’image donnée en entrée au format bitmap aussi.
Le programme principal écrit en C, negatif.c, est disponible ci-après, il fait appel à une procédure
écrite en langage d’assemblage dans le fichier util.s, que vous devez le compléter par la procédure
NEG et la fonction NON OCT décrites ci-dessous.
Les conventions de passage des paramètres sont : l’adresse du tableau est dans r0, la valeur de n
est dans r1.
La fonction NON OCT est utilisée par la procédure NEG pour calculer la négation bit à bit d’un octet.
Cette fonction est locale à ce fichier.
Les conventions de passage du paramètre et du résultat sont : l’octet donnée est dans r4, l’octet
résultat est dans r5.
Le programme lit le fichier charlot.bm et produit le fichier resultat.bm. Pour afficher ces fichiers,
utiliser la commande bitmap (cf. le premier TP).
6.2.3 util.s
.text
.global NEG
NEG:
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 102
@ a completer
NON_OCT:
@ a completer
6.2.4 negatif.c
/* transformation d’un image au format bitmap en son image negative
*
* le programme produit un fichier resultat.bm
*
* ce programme fait appel a la procedure NEG qui transforme
* un tableau de bits en sa negation bit a bit
*
*/
#include <stdio.h>
#include "charlot.bm"
/* ****************************************** */
/* appel d’une procedure ecrite en assembleur */
/* ****************************************** */
/* ****************************************** */
/* version en C */
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 103
/*
for (i=0;i<nboctets;i++) {
charlot_bits[i] = ~charlot_bits[i];
}
*/
/* ****************************************** */
6.3.1 symetrie.c
#include <stdio.h>
#include "commun.h"
#include "charlot.bm"
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 104
#ifndef SYMTAB
void symetrie_octet (unsigned char *adresse) {
unsigned char octet;
octet = *adresse;
*adresse = octet;
}
#else
#include "tabsym.h"
octet = *adresse;
octet = tabsym_octet[octet];
*adresse = octet;
}
#endif
void permuter_ligne (unsigned char *tab, unsigned int octets_par_ligne, unsigned int col) {
unsigned char tmp;
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 105
}
}
6.3.2 commun.h
fndef _COMMUN_H_
#define _COMMUN_H_
#ifndef OCTETS_PAR_LIGNE_DU_FICHIER
#define OCTETS_PAR_LIGNE_DU_FICHIER 16
#endif
void doinit();
void afficher_contenu (void);
void rectangle (unsigned int xhg,unsigned int yhg, unsigned int xbd, unsigned
int ybd,
octet_fonc_t f, unsigned char *image);
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 106
#endif
6.3.3 tabsym.h
static const unsigned char tabsym_octet [256] = {
0x00,0x80,0x40,0xc0,0x20,0xa0,0x60,0xe0,0x10,0x90,0x50,0xd0,0x30,0xb0,0x70,0xf0,
0x08,0x88,0x48,0xc8,0x28,0xa8,0x68,0xe8,0x18,0x98,0x58,0xd8,0x38,0xb8,0x78,0xf8,
0x04,0x84,0x44,0xc4,0x24,0xa4,0x64,0xe4,0x14,0x94,0x54,0xd4,0x34,0xb4,0x74,0xf4,
0x0c,0x8c,0x4c,0xcc,0x2c,0xac,0x6c,0xec,0x1c,0x9c,0x5c,0xdc,0x3c,0xbc,0x7c,0xfc,
0x02,0x82,0x42,0xc2,0x22,0xa2,0x62,0xe2,0x12,0x92,0x52,0xd2,0x32,0xb2,0x72,0xf2,
0x0a,0x8a,0x4a,0xca,0x2a,0xaa,0x6a,0xea,0x1a,0x9a,0x5a,0xda,0x3a,0xba,0x7a,0xfa,
0x06,0x86,0x46,0xc6,0x26,0xa6,0x66,0xe6,0x16,0x96,0x56,0xd6,0x36,0xb6,0x76,0xf6,
0x0e,0x8e,0x4e,0xce,0x2e,0xae,0x6e,0xee,0x1e,0x9e,0x5e,0xde,0x3e,0xbe,0x7e,0xfe,
0x01,0x81,0x41,0xc1,0x21,0xa1,0x61,0xe1,0x11,0x91,0x51,0xd1,0x31,0xb1,0x71,0xf1,
0x09,0x89,0x49,0xc9,0x29,0xa9,0x69,0xe9,0x19,0x99,0x59,0xd9,0x39,0xb9,0x79,0xf9,
0x05,0x85,0x45,0xc5,0x25,0xa5,0x65,0xe5,0x15,0x95,0x55,0xd5,0x35,0xb5,0x75,0xf5,
0x0d,0x8d,0x4d,0xcd,0x2d,0xad,0x6d,0xed,0x1d,0x9d,0x5d,0xdd,0x3d,0xbd,0x7d,0xfd,
0x03,0x83,0x43,0xc3,0x23,0xa3,0x63,0xe3,0x13,0x93,0x53,0xd3,0x33,0xb3,0x73,0xf3,
0x0b,0x8b,0x4b,0xcb,0x2b,0xab,0x6b,0xeb,0x1b,0x9b,0x5b,0xdb,0x3b,0xbb,0x7b,0xfb,
0x07,0x87,0x47,0xc7,0x27,0xa7,0x67,0xe7,0x17,0x97,0x57,0xd7,0x37,0xb7,0x77,0xf7,
0x0f,0x8f,0x4f,0xcf,0x2f,0xaf,0x6f,0xef,0x1f,0x9f,0x5f,0xdf,0x3f,0xbf,0x7f,0xff
};
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 107
Chapitre 7
Le code en langage d’assemblage ARM d’un programme en C peut être produit sans optimisation
par le compilateur gcc avec l’option -O0. Dans ce TP, nous allons observer ce qu’un compilateur peut
optimiser. Nous allons reprendre les mêmes programmes et codes du chapitre II.10, éventuellement
modifiés mais en les compilant avec un niveau d’optimisation important (option -O2).
Pour ce TP n’hésitez pas à faire d’autres essais que ceux qui sont proposés.
Un autre objectif du TP est de distinguer :
— ce qui est du domaine du “statique”, c’est-à-dire ce qui peut être calculé lors de la compilation,
— ce qui est du domaine du “dynamique”, c’est-à-dire ce qui ne peut être calculé que lors de
l’exécution.
1 #include "stdio.h"
2
3 static long int Somme (long int a1, long int a2, long int a3, long int a4, long
int a5,
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 108
4 long int a6, long int a7, long int a8, long int a9, long
int a10) {
5 long int x1,x2,x3,x4,x5,x6,x7,x8,x9,x10;
6 long int y;
7
8 x1=a1+1; x2=a2+1; x3=a3+1; x4=a4+1; x5=a5+1;
9 x6=a6+1; x7=a7+1; x8=a8+1; x9=a9+1; x10=a10+1;
10 y = x1+x2+x3+x4+x5+x6+x7+x8+x9+x10;
11 return (y);
12 }
13
14 int main () {
15 long int z; long int u1, u2, u3, u4, u5, u6, u7, u8, u9, u10;
16
17 scanf ("%d", &u1);
18 scanf ("%d", &u2);
19 scanf ("%d", &u3);
20 scanf ("%d", &u4);
21 scanf ("%d", &u5);
22 scanf ("%d", &u6);
23 scanf ("%d", &u7);
24 scanf ("%d", &u8);
25 scanf ("%d", &u9);
26 scanf ("%d", &u10);
27 z = Somme (u1, u2, u3, u4, u5, u6, u7, u8, u9, u10);
28 printf("La somme des entiers vaut %d\n", z);
29 }
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 109
7.3 Les variables locales peuvent prendre beaucoup de place
Soit le programme contenu dans le fichier var pile.c. Compilez ce programme avec la commande :
arm-aebi-gcc -O2 -S var pile.c. Etudiez le programme produit dans var pile.s et comparez avec
le code étudié dans le chapitre II.10.
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 110
Chapitre 8
TP séances 12 : Procédures et
paramètres
. map : procédure avec quatre paramètres des types : TabEnt8, EntN, TabEnt8 et FoncMapEnt8
{
map(t1, n, t2, f) : t1 est un tableau qui contient une séquence de n entiers
du type Ent8, déjà t2 est un tableau qui contient la séquence avec les résultats
du type Ent8 de la fonction f du type FoncMapEnt8 : [f(t1[0]), f(t1[1]), ..., f(t1[n-1])]
}
On s’intéresse à la procédure map. Une réalisation en est donnée par l’algorithme suivant :
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 111
map(t1, n, t2, f) :
i : entier du type EntN
i <- 0
tant que i != n
t2[i] <- f(t1[i])
i <- i + 1
Exercice 1 :
1. Traduire l’algorithme en langage d’assemblage Arm : compléter la définition de la procédure
map (fichier map.s, cf. annexe I).
2. Compléter le corps de la procédure principale main du fichier essai-map.s (cf. annexe III) : vous
devez ajouter aux endroits voulus de ce fichier deux appels à la procédure map et pour chacun
d’eux un appel à la procédure auxillaire afficher tab (fichier gestion tab.s, cf. annexe VI).
La procédure map sera invoquée une première fois avec la fonction plus un comme un paramètre
telle que : plus un(x) = x+1 et une seconde fois avec la fonction carre telle que : carre(x) = x2
(fichier fg.s, cf. annexe II).
3. Compilez et testez le programme (faites un fichier Makefile permettant d’utiliser la commande
make pour compiler le programme).
. red : fonction avec quatre paramètres des types TabEnt8, EntN, Ent8 et
FoncRedEnt8 et un retour du type Ent32
{
si n > 0 : red(t, n, vi, g) = g( ... (g(g(g(vi, t[0]), t[1]), t[2]), ..., t[n - 1]) ... )
si n = 0 : red(t, 0, vi, g) = vi
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 112
}
Pn−1
Si g est la fonction somme telle que : somme(x, y) = x + y, alors red(t, n, 0, somme) = i=0 t[i].
Une réalisation de la fonction red est donnée par l’algorithme suivant :
red(t, n, vi, g) :
i : entier du type EntN
acc : entier du type Ent32
i <- 0
acc <- vi
tant que i != n
acc <- g(acc, t[i])
i <- i + 1
retour acc
Exercice 2 :
1. Traduire l’algorithme en langage d’assemblage Arm : compléter la définition de la fonction red
(fichier red.s, cf. annexe IV).
2. Compléter le corps de la procédure principale main du fichier essai-red.s (cf. annexe V). Vous
devez ajouter aux endroits voulus de ce fichier un appel à la fonction red ainsi qu’un appel à
l’une des deux procédures auxillaires EcrZdecimal32 ou EcrZdecim32 (cf. fichier es.s).
La fonction red sera invoquée avec la fonction somme comme un paramètre telle que :
somme(x, y) = x + y (fichier fg.s, cf. annexe II).
3. Compilez et testez le programme.
Qn−1
8.2.2 Calcul de i=0 T [i]
Exercice 3 :
1. Quels
Qn−1 sont-ils les paramètres à passer à la fonction red pour effectuer le calcul du produit
i=0 T [i] ?
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 113
8.3 Passage de paramètres par la pile
Exercice 4 :
On veut réaliser une nouvelle version de la procédure map, ou de la fonction red, en utilisant cette
fois-ci le passage de paramètres par la pile plutôt que par les registres. Choisissez une organisation
de la pile appropriée pour le passage des paramètres (le schéma correspondant sera à inclure dans le
compte-rendu du TP), puis réalisez une nouvelle version du programme (dans les fichier map2.s et
essai-map2.s, ou red2.s et essai-red2.s, par exemple).
.text
.global map
map:
@@@@@@@@@@@@@
@ A COMPLETER
@@@@@@@@@@@@@
mov r0, r3
mov r1, r3
bl mult
mov r4, r0
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 114
add sp, sp, #4
ldr r0, [sp]
add sp, sp, #4
ldr lr, [sp]
add sp, sp, #4
mov pc, lr
.data
invite1: .asciz "Saisir une sequence de "
invite2: .asciz " entiers :"
afftab1: .asciz "Sequence donnee S :"
afftab2: .asciz "map(S, plus_un) :"
afftab3: .asciz "map(S, carre) :"
tab1: .skip NMAX @ tableau de NMAX octets
tab2: .skip NMAX @ tableau de NMAX octets
.text
.global main
@ procedure principale
main:
@ saisir la sequence donnee
ldr r1, adr_invite1
bl EcrChn
mov r1, #NMAX
bl EcrNdecim32
ldr r1, adr_invite2
bl EcrChaine
ldr r0, adr_tab1
mov r1, #NMAX
bl saisir_tab
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 115
bl afficher_tab
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 116
@ fonction red
@ parametres : A COMPLETER
@ algorithme : A COMPLETER
red:
@@@@@@@@@@@@@
@ A COMPLETER
@@@@@@@@@@@@@
.data
invite1: .asciz "Saisir une sequence de "
invite2: .asciz " entiers :"
afftab: .asciz "Sequence donnee S :"
affres1: .asciz "red(S, somme) = "
tab : .skip NMAX @ tableau de NMAX octets
var_somme: .byte 0
.text
.global main
@ procedure principale
main:
@ saisir la sequence donnee
ldr r1, adr_invite1
bl EcrChn
mov r1, #NMAX
bl EcrNdecim32
ldr r1, adr_invite2
bl EcrChaine
ldr r0, adr_tab
mov r1, #NMAX
bl saisir_tab
@ afficher le resultat
bl AlaLigne
ldr r1, adr_affres1
bl EcrChn
@@@@@@@@@@@@@
@ A COMPLETER
@@@@@@@@@@@@@
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 117
@ fin du programme principal
bal exit
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 118
Annexe VI : le fichier gestion tab.s
.data
entier: .byte 0 @ entiers de la sequence
.text
.global saisir_tab, afficher_tab
saisir_tab:
sub sp, sp, #4 @ sauvegarde adresse de retour
str lr, [sp]
sub sp, sp, #4 @ sauvegarde temporaires
str r1, [sp]
sub sp, sp, #4
str r2, [sp]
sub sp, sp, #4
str r5, [sp]
sub sp, sp, #4
str r6, [sp]
tantque1:
cmp r5, r6
beq fintq1
ldr r1, adr_entier @ lire un entier
bl Lire8
ldrb r2, [r1]
strb r2, [r0, r5] @ le ranger dans le tableau
add r5, r5, #1 @ octet suivant
bal tantque1
fintq1:
ldr r6, [sp] @ restauration temporaires
add sp, sp, #4
ldr r5, [sp]
add sp, sp, #4
ldr r2, [sp]
add sp, sp, #4
ldr r1, [sp]
add sp, sp, #4
ldr lr, [sp] @ restauration adresse de retour
add sp, sp, #4
mov pc, lr @ retour a l’appelant
adr_entier:
.word entier
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 119
afficher_tab:
sub sp, sp, #4 @ sauvegarde adresse de retour
str lr, [sp]
sub sp, sp, #4 @ sauvegarde temporaires
str r1, [sp]
sub sp, sp, #4
str r5, [sp]
sub sp, sp, #4
str r6, [sp]
sub sp, sp, #4
str r7, [sp]
@ corps de la procedure
mov r5, #0 @ indice dans tableau
mov r6, r0 @ adresse de debut
mov r7, r1 @ taille du tableau
tantque2:
cmp r5, r7
beq fintq2
ldrb r1, [r6, r5] @ on recupere l’octet courant
bl EcrZdecim8 @ qui est imprime
mov r1, #’ ’
bl EcrCar @ en le separant du suivant par un espace
add r5, r5, #1 @ octet suivant
bal tantque2
fintq2:
bl AlaLigne
ldr r7, [sp] @ restauration temporaires
add sp, sp, #4
ldr r6, [sp]
add sp, sp, #4
ldr r5, [sp]
add sp, sp, #4
ldr r1, [sp]
add sp, sp, #4
ldr lr, [sp] @ restauration adresse de retour
add sp, sp, #4
mov pc, lr @ retour a l’appelant
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 120
Quatrième partie
Annexes
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 121
Chapitre 1
Dec Hex Char Dec Hex Char Dec Hex Char Dec Hex Char
0 00 NUL 32 20 SPACE 64 40 @ 96 60 ‘
1 01 SOH 33 21 ! 65 41 A 97 61 a
2 02 STX 34 22 ” 66 42 B 98 62 b
3 03 ETX 35 23 # 67 43 C 99 63 c
4 04 EOT 36 24 $ 68 44 D 100 64 d
5 05 ENQ 37 25 % 69 45 E 101 65 e
6 06 ACK 38 26 & 70 46 F 102 66 f
7 07 BEL 39 27 ’ 71 47 G 103 67 g
8 08 BS 40 28 ( 72 48 H 104 68 h
9 09 HT 41 29 ) 73 49 I 105 69 i
10 0A LF 42 2A * 74 4A J 106 6A j
11 0B VT 43 2B + 75 4B K 107 6B k
12 0C FF 44 2C , 76 4C L 108 6C l
13 0D CR 45 2D - 77 4D M 109 6D m
14 0E SO 46 2E . 78 4E N 110 6E n
15 0F SI 47 2F / 79 4F O 111 6F o
16 10 DLE 48 30 0 80 50 P 112 70 p
17 11 DC1 49 31 1 81 51 Q 113 71 q
18 12 DC2 50 32 2 82 52 R 114 72 r
19 13 DC3 51 33 3 83 53 S 115 73 s
20 14 DC4 52 34 4 84 54 T 116 74 t
21 15 NAK 53 35 5 85 55 U 117 75 u
22 16 SYN 54 36 6 86 56 V 118 76 v
23 17 ETB 55 37 7 87 57 W 119 77 w
24 18 CAN 56 38 8 88 58 X 120 78 x
25 19 EM 57 39 9 89 59 Y 121 79 y
26 1A SUB 58 3A : 90 5A Z 122 7A z
27 1B ESC 59 3B ; 91 5B [ 123 7B {
28 1C FS 60 3C < 92 5C \ 124 7C |
29 1D GS 61 3D = 93 5D ] 125 7D }
30 1E RS 62 3E > 94 5E ˆ 126 7E ˜
31 1F US 63 3F ? 95 5F 127 7F DEL
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 122
Chapitre 2
La figure 2.1 illustre les représentations d’entiers naturels et signés pour une taille de mot de 4 bits.
A chaque entier peut être associé un angle. Effectuer une addition revient à ajouter les angles cor-
respondant. Un débordement de produit au-delà d’un demi-tour en arithmétique signée ou d’un tour
complet en arithmétique naturelle.
n 2n
décimal hexa octal binaire décimal hexa commentaire
0 0 00 0000 1 1
1 1 01 0001 2 2
2 2 02 0010 4 4
3 3 03 0011 8 8
4 4 04 0100 16 10 un quartet = un chiffre hexa
5 5 05 0101 32 20
6 6 06 0110 64 40
7 7 07 0111 128 80
8 8 10 1000 256 100 un octet = deux chiffres hexa
9 9 11 1001 512 200
10 A 12 1010 1024 400 1Kb
11 B 13 1011 2048 800 2Kb
12 C 14 1100 4096 1000 4Kb
13 D 15 1101 8192 2000 8Kb
14 E 16 1110 16384 4000 16Kb
15 F 17 1111 32768 8000 32Kb
16 10 20 10000 65536 10000 64Kb
20 14 24 10100 1048576 100000 1Mb = 1Kb2 = 5 chiffres
30 1E 36 11110 ˜1.07 × 109 40000000 1Gb = 1Kb3
Les tableaux ci-dessus et ci-dessous récapitulent les principales puissances de 2 utiles, avec leur
représentation en hexadécimal et les puissances de 10 approchées correspondantes, ainsi que les types C
entiers de taille précise (utiliser la taille en octets pour les réservations de mémoire et les alignements).
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 123
Chapitre 3
@ Convention d’appel :
@ en entree, a : r0 ; b : r1 ; parametre temporaire, resultat : r2;
@ valeur retour : r0 (attention le r0 en entree est ecrase’)
.text
.global mult
mult:
stmfd sp!, {r1,r2}
mov r2,#0
b ctq
tq: tst r0,#1 @ (a&1)
addne r2,r2,r1 @ ajouter b si a_0 == 1
mov r1,r1, LSL #1
mov r0,r0, LSR #1
ctq: cmp r0,#0
bne tq
mov r0,r2 @ return resultat
ldmfd sp!,{r1,r2}
mov pc,lr
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 124
Chapitre 4
@ fichier es.s
@ fonctions d’entrees sorties
@ AlaLigne :
@ retour a la ligne
@ EcrCar :
@ ecriture d’un caractère dont la valeur est dans r1
@ EcrChn :
@ ecriture de la chaine sans retour à la ligne dont l’adresse est dans r1
@ EcrChaine :
@ ecriture de la chaine dont l’adresse est dans r1
@ EcrHexa32 :
@ ecriture d’un mot de 32 bits en hexadécimal
@ la valeur a afficher est dans r1
@ EcrZdecimalf32 :
@ ecriture en decimal d’un entier relatif represente sur 32 bits
@ l’entier est dans r1
@ EcrZdecimal16 :
@ ecriture en decimal d’un entier relatif represente sur 16 bits
@ l’entier est dans les 16 bits de poids faibles de r1
@ EcrZdecimal8 :
@ ecriture en decimal d’un entier relatif represente sur 8 bits
@ l’entier est dans les 8 bits de poids faibles de r1
@ attention : les bits 15 a 8 de r1 sont eventuellement modifies
@ EcrNdecimal32 :
@ ecriture en decimal d’un entier naturel represente sur 32 bits
@ l’entier est dans r1
@ EcrNdecimal16 :
@ ecriture en decimal d’un entier naturel represente sur 16 bits
@ l’entier est dans les 16 bits de poids faibles de r1
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 125
@ EcrNdecimal8 :
@ ecriture en decimal d’un entier naturel represente sur 8 bits
@ l’entier est dans les 8 bits de poids faibles de r1
@ attention : les bits 15 a 8 de r1 sont mis a 0
@ Lire32 :
@ lecture d’un entier represente sur 32 bits
@ l’adresse de l’entier doit etre donnee dans r1
@ Lire16 :
@ lecture d’un entier represente sur 16 bits
@ l’adresse de l’entier doit etre donnee dans r1
@ Lire8 :
@ lecture d’un entier represente sur 8 bits
@ l’adresse de l’entier doit etre donnee dans r1
@ LireCar :
@ lecture d’un caractere tape au clavier
@ l’adresse du caractere (code en ascii) doit etre donnee dans r1
Equipe
c d’Enseignement INF401 ALM de l’UJF - 11 décembre 2017 126