Normale Superieure
Langages de programmation
et compilation
Jean-Christophe Filliatre
Cours 2 / 2 octobre 2014
compilation
langage source
compilateur
langage cible
erreurs
Jean-Christophe Filli
atre
20142015 / cours 2
2 / 85
compilateur C (gcc)
Jean-Christophe Filli
atre
executable sum
00100111101111011111111111100000
10101111101111110000000000010100
10101111101001000000000000100000
10101111101001010000000000100100
10101111101000000000000000011000
10101111101000000000000000011100
10001111101011100000000000011100
...
20142015 / cours 2
3 / 85
langage cible
dans ce cours, nous allons effectivement nous interesser `a la compilation
vers de lassembleur, mais ce nest quun aspect de la compilation
un certain nombre de techniques mises en uvre dans la compilation ne
sont pas liees `a la production de code assembleur
certains langages sont dailleurs
interpretes (Basic, COBOL, Ruby, Python, etc.)
compiles dans un langage intermediaire qui est ensuite interprete
(Java, OCaml, etc.)
compiles vers un autre langage de haut niveau
compiles `a la volee
Jean-Christophe Filli
atre
20142015 / cours 2
4 / 85
Jean-Christophe Filli
atre
20142015 / cours 2
5 / 85
dit autrement,
le compilateur fait un travail complexe une seule fois, pour produire un
code fonctionnant pour nimporte quelle entree
linterpr`ete effectue un travail plus simple, mais le refait sur chaque entree
autre difference : le code compile est generalement bien plus efficace que
le code interprete
Jean-Christophe Filli
atre
20142015 / cours 2
6 / 85
lilypond
gs
fichier PostScript
image
<<
\chords { c2 c f2 c }
\new Staff \relative c { \time 2/4 c4 c g4 g a4 a g2 }
\new Lyrics \lyricmode { twin4 kle twin kle lit tle star2
>>
42
20142015 / cours 2
7 / 85
Jean-Christophe Filli
atre
20142015 / cours 2
8 / 85
Jean-Christophe Filli
atre
20142015 / cours 2
9 / 85
phase danalyse
source
analyse lexicale
analyse syntaxique
analyse semantique
Jean-Christophe Filli
atre
20142015 / cours 2
10 / 85
phase de synth`ese
syntaxe abstraite
langage assembleur
assembleur (as)
langage machine
code executable
Jean-Christophe Filli
atre
20142015 / cours 2
11 / 85
aujourdhui
assembleur
Jean-Christophe Filli
atre
20142015 / cours 2
12 / 85
bn2
...
b1
b0
Jean-Christophe Filli
atre
20142015 / cours 2
13 / 85
bits
000. . .000
000. . .001
000. . .010
..
.
valeur
0
1
2
..
.
111. . .110
111. . .111
2n 2
2n 1
exemple : 001010102 = 42
Jean-Christophe Filli
atre
20142015 / cours 2
14 / 85
exemple :
110101102 = 128 + 86
= 42
Jean-Christophe Filli
atre
bits
100. . .000
100. . .001
..
.
valeur
2n1
2n1 + 1
..
.
111. . .110
111. . .111
000. . .000
000. . .001
000. . .010
..
.
2
1
0
1
2
..
.
011. . .110
011. . .111
2n1 2
2n1 1
20142015 / cours 2
15 / 85
attention
Jean-Christophe Filli
atre
20142015 / cours 2
16 / 85
operations
Jean-Christophe Filli
atre
20142015 / cours 2
17 / 85
operations logiques
op
eration
negation
x
NOT x
00101001
11010110
ET
x
y
x AND y
00101001
01101100
00101000
OU
x
y
x OR y
00101001
01101100
01101101
x
y
x XOR y
00101001
01101100
01000101
OU exclusif
Jean-Christophe Filli
atre
exemple
20142015 / cours 2
18 / 85
operations de decalages
b1 b0 0 0
b3 b2
Jean-Christophe Filli
atre
b3 b2
20142015 / cours 2
19 / 85
un peu darchitecture
Jean-Christophe Filli
atre
20142015 / cours 2
20 / 85
un peu darchitecture
RAM
CPU
$pc 0000052
lacc`es `a la memoire co
ute cher (`a un milliard dinstructions par seconde,
la lumi`ere ne parcourt que 30 centim`etres entre 2 instructions !)
Jean-Christophe Filli
atre
20142015 / cours 2
21 / 85
un peu darchitecture
Jean-Christophe Filli
atre
20142015 / cours 2
22 / 85
principe dexecution
Jean-Christophe Filli
atre
20142015 / cours 2
23 / 85
principe dexecution
RAM
CPU
$pc 0000052
20142015 / cours 2
24 / 85
principe dexecution
prediction de branchement
pour optimiser le pipeline, on tente de predire les sauts conditionnels
Jean-Christophe Filli
atre
20142015 / cours 2
25 / 85
Jean-Christophe Filli
atre
20142015 / cours 2
26 / 85
larchitecture MIPS
Jean-Christophe Filli
atre
20142015 / cours 2
27 / 85
larchitecture MIPS
32 registres, $0 `a $31
$0 contient toujours 0
utilisables sous dautres noms, correspondant `a des conventions
(zero, at, v0v1, a0a3, t0t9, s0s7, k0k1, gp, sp, fp, ra)
Jean-Christophe Filli
atre
20142015 / cours 2
28 / 85
assembleur MIPS
Jean-Christophe Filli
atre
20142015 / cours 2
29 / 85
assembleur MIPS
la directive
.text
7FFFFFFC16
.data
indique que des donnees suivent
le code sera charge `a partir de ladresse 0x400000
et les donnees `a partir de ladresse 0x10000000
Jean-Christophe Filli
atre
donnees
1000000016
code
40000016
(reserve)
20142015 / cours 2
30 / 85
main:
hw:
.text
li
la
syscall
li
syscall
.data
.asciiz
$v0, 4
$a0, hw
$v0, 10
#
#
#
#
code de print_string
adresse de la cha^
ne
appel syst`
eme
exit
"hello world\n"
Jean-Christophe Filli
atre
20142015 / cours 2
31 / 85
simulateurs MIPS
Jean-Christophe Filli
atre
20142015 / cours 2
32 / 85
$a0, 42
$a0, -65536
# a0 <- 42
# a0 <- -65536
$a0, label
Jean-Christophe Filli
atre
# copie a1 dans a0 !
20142015 / cours 2
33 / 85
# a0 <- a1 + a2
# a2 <- a2 + t5
# a0 <- a1 + 42
$a0, $a1
# a0 <- -a1
$a0, $a1
# a0 <- |a1|
valeur absolue
abs
Jean-Christophe Filli
atre
20142015 / cours 2
34 / 85
$a0, $a1
# a0 <- not(a1)
Jean-Christophe Filli
atre
20142015 / cours 2
35 / 85
# a0 <- a1 * 4
# a1 <- a2 * 2^a3
$a0, $a1, 2
# a0 <- a1 / 4
$a0, $a1, 2
rol
ror
$a0, $a1, 2
$a0, $a1, 3
rotation
Jean-Christophe Filli
atre
20142015 / cours 2
36 / 85
# a0 <- 1 si a1 < a2
#
0 sinon
Jean-Christophe Filli
atre
20142015 / cours 2
37 / 85
$a0, 42($a1)
Jean-Christophe Filli
atre
20142015 / cours 2
38 / 85
$a0, 42($a1)
Jean-Christophe Filli
atre
20142015 / cours 2
39 / 85
on distingue
branchement : typiquement un saut conditionnel, dont le
deplacement est stocke sur 16 bits signes (-32768 `a 32767
instructions)
saut : saut inconditionnel, dont ladresse de destination est stockee
sur 26 bits
Jean-Christophe Filli
atre
20142015 / cours 2
40 / 85
branchement conditionnel
beq
variantes : bne, blt, ble, bgt, bge (et comparaisons non signees)
variantes : beqz, bnez, bgez, bgtz, bltz, blez
Jean-Christophe Filli
atre
20142015 / cours 2
41 / 85
label
label
$a0
20142015 / cours 2
42 / 85
# code de print_int
# valeur `
a afficher
Jean-Christophe Filli
atre
20142015 / cours 2
43 / 85
pseudo-instructions
$a0, 42
lassembleur le traduit en
addiu $a0, $zero, 42
Jean-Christophe Filli
atre
20142015 / cours 2
44 / 85
pseudo-instructions
autre exemple :
si letiquette hw correspond `a ladresse 0x10010020, linstruction
la
$a0, hw
est traduite en
lui
ori
$at, 0x1001
$a0, $at, 0x0020
Jean-Christophe Filli
atre
20142015 / cours 2
45 / 85
le defi de la compilation
Jean-Christophe Filli
atre
20142015 / cours 2
46 / 85
appels de fonctions
Jean-Christophe Filli
atre
20142015 / cours 2
47 / 85
la pile
pile
donnees
dynamiques
(tas)
donnees
statiques
code
Jean-Christophe Filli
atre
20142015 / cours 2
48 / 85
appel de fonction
lorsquune fonction f (lappelant ou caller ) souhaite appeler une fonction
g (lappele ou callee), elle execute
jal
$ra
probl`eme :
si g appelle elle-meme une fonction, $ra sera ecrase
de meme, tout registre utilise par g sera perdu pour f
il existe de multiples mani`eres de sen sortir,
mais en general on saccorde sur des conventions dappel
Jean-Christophe Filli
atre
20142015 / cours 2
49 / 85
conventions dappel
utilisation des registres
$at, $k0 et $k1 sont reserves `a lassembleur et lOS
$a0$a3 sont utilises pour passer les quatre premiers arguments (les
autres sont passes sur la pile) et $v0$v1 pour renvoyer le resultat
$t0$t9 sont des registres caller-saved i.e. lappelant doit les
sauvegarder si besoin ; on y met donc typiquement des donnees qui
nont pas besoin de survivre aux appels
$s0$s7 sont des registres callee-saved i.e. lappele doit les
sauvegarder ; on y met donc des donnees de duree de vie longue,
ayant besoin de survivre aux appels
$sp est le pointeur de pile, $fp le pointeur de frame
$ra contient ladresse de retour
$gp pointe au milieu de la zone de donnees statiques (1000800016 )
Jean-Christophe Filli
atre
20142015 / cours 2
50 / 85
Jean-Christophe Filli
atre
20142015 / cours 2
51 / 85
passe les arguments dans $a0$a3, les autres sur la pile sil y en a
plus de 4
execute
jal
Jean-Christophe Filli
atre
appel
e
20142015 / cours 2
52 / 85
registres
sauves
$fp
$fp, 24($sp)
$fp, $sp, 24
...
argument 5
argument 6
variables
locales
$sp
Jean-Christophe Filli
atre
20142015 / cours 2
53 / 85
$fp, 24($sp)
execute
jr
Jean-Christophe Filli
atre
$ra
20142015 / cours 2
54 / 85
Jean-Christophe Filli
atre
20142015 / cours 2
55 / 85
exercice 1
Jean-Christophe Filli
atre
20142015 / cours 2
56 / 85
exercice 2
Jean-Christophe Filli
atre
20142015 / cours 2
57 / 85
recapitulation
Jean-Christophe Filli
atre
20142015 / cours 2
58 / 85
un exemple de compilation
t(a,b,c){int d=0,e=a&~b&~c,f=1;if(a)
for(f=0;d=(e-=d)&-e;f+=t(a-d,(b+d)*2,
(c+d)/2));return f;}main(q){scanf("%d",
&q);printf("%d\n",t(~(~0<<q),0,0));}
Jean-Christophe Filli
atre
20142015 / cours 2
59 / 85
clarification
Jean-Christophe Filli
atre
20142015 / cours 2
60 / 85
clarification (suite)
int t(int a, int b, int c) {
int f=1;
if (a) {
int d, e=a&~b&~c;
f = 0;
while (d=e&-e) {
f += t(a-d, (b+d)*2, (c+d)/2);
e -= d;
}
}
return f;
}
int main() {
int q;
scanf("%d", &q);
printf("%d\n", t(~(~0<<q), 0, 0));
}
Jean-Christophe Filli
atre
ce programme calcule
le nombre de solutions
du probl`eme dit
des n reines
q
q
q
q
q
20142015 / cours 2
q
q
61 / 85
comment ca marche ?
recherche par force brute (backtracking )
entiers utilises comme des ensembles :
par ex. 13 = 0 011012 = {0, 2, 3}
entiers
0
a&b
a+b
a-b
~a
a&-a
~(~0<<n)
a*2
a/2
Jean-Christophe Filli
atre
ensembles
ab
a b, quand a b =
a\ b, quand b a
{a
{min(a)}, quand a 6=
{0, 1, . . . , n 1}
{i + 1 | i a}, note S(a)
{i 1 | i a i 6= 0}, note P(a)
20142015 / cours 2
62 / 85
justification de a&-a
en complement `a deux : -a = ~a+1
a = bn1 bn2 . . . bk 10 . . . 0
~a = bn1 bn2 . . . bk 01 . . . 1
-a = bn1 bn2 . . . bk 10 . . . 0
a&-a =
0 . . . 010 . . . 0
exemple :
a = 00001100 = 12
-a = 11110100 = 128 + 116
a&-a = 00000100
Jean-Christophe Filli
atre
20142015 / cours 2
63 / 85
int t(a, b, c)
f 1
if a 6=
e (a\b)\c
f 0
while e 6=
d min(e)
f f + t(a\{d}, S(b {d}), P(c {d}))
e e\{d}
return f
int queens(n)
return t({0, 1, . . . , n 1}, , )
Jean-Christophe Filli
atre
20142015 / cours 2
64 / 85
signification de a, b et c
? ? ? ? ? ? ? ?
q
qqq
Jean-Christophe Filli
atre
q
q
q
20142015 / cours 2
65 / 85
20142015 / cours 2
66 / 85
compilation
Jean-Christophe Filli
atre
20142015 / cours 2
67 / 85
allocation de registres
a, b et c sont passes dans $a0, $a1 et $a2
le resultat est renvoye dans $v0
les param`etres a, b, c, tout comme les variables locales d, e, f, ont
besoin detre sauvegardes, car ils sont utilises apr`es lappel recursif
on va utiliser des registres callee-save
a $s0
b $s1
c $s2
d $s3
e $s4
f $s5
il faut donc allouer 7 mots sur la pile pour sauvegarder ladresse de
retour $ra et ces 6 registres
Jean-Christophe Filli
atre
20142015 / cours 2
68 / 85
addi
sw
sw
sw
sw
sw
sw
sw
...
lw
lw
lw
lw
lw
lw
lw
addi
jr $ra
Jean-Christophe Filli
atre
$sp,
$ra,
$s0,
$s1,
$s2,
$s3,
$s4,
$s5,
$sp, -28
24($sp)
20($sp)
16($sp)
12($sp)
8($sp)
4($sp)
0($sp)
# allocation de 7 mots
# sauvegarde des registres
$ra,
$s0,
$s1,
$s2,
$s3,
$s4,
$s5,
$sp,
24($sp)
20($sp)
16($sp)
12($sp)
8($sp)
4($sp)
0($sp)
$sp, 28
# d
esallocation
20142015 / cours 2
69 / 85
compilation du test
Jean-Christophe Filli
atre
li
beqz
...
t return:
move
$s5, 1
$a0, t return
$v0, $s5
20142015 / cours 2
70 / 85
cas general (a 6= 0)
if (a) {
int d, e=a&~b&~c;
f = 0;
while ...
}
move
move
move
move
not
and
not
and
li
$s0,
$s1,
$s2,
$s4,
$t0,
$s4,
$t0,
$s4,
$s5,
$a0 # sauvegarde
$a1
$a2
$s0 # e=a&~b&~c
$s1
$s4, $t0
$s2
$s4, $t0
0
# f = 0
Jean-Christophe Filli
atre
20142015 / cours 2
71 / 85
compilation de la boucle
L1:
while (test) {
body
}
L2:
Jean-Christophe Filli
atre
...
...
calcul de test dans $t0
...
beqz $t0, L2
...
body
...
j L1
...
20142015 / cours 2
72 / 85
compilation de la boucle
il existe cependant une meilleure solution
L1:
while (test) {
body
}
L2:
...
j L2
...
body
...
...
test
...
bnez $t0, L1
20142015 / cours 2
73 / 85
compilation de la boucle
j
test
sub
add
sll
add
srl
jal
add
sub
$a0,
$a1,
$a1,
$a2,
$a2,
t
$s5,
$s4,
body:
while (d=e&-e) {
f += t(a-d,
(b+d)*2,
(c+d)/2);
e -= d;
}
$s0,
$s1,
$a1,
$s2,
$a2,
$s3 # a-d
$s3 # (b+d)*2
1
$s3 # (c+d)/2
1
$s5, $v0
$s4, $s3 # e -= d
test:
neg $t0, $s4
# d=e&-e
and $s3, $s4, $t0
bnez $s3, body
t return:
...
Jean-Christophe Filli
atre
20142015 / cours 2
74 / 85
programme principal
main:
li
$v0,
syscall
li
$a0,
not $a0,
sllv $a0,
not $a0,
int main() {
li
$a1,
int q;
li
$a2,
scanf("%d", &q);
jal t
printf("%d\n",
move $a0,
t(~(~0<<q), 0, 0));
li
$v0,
}
syscall
li
$v0,
la
$a0,
syscall
li
$v0,
syscall
Jean-Christophe Filli
atre
# read_int
0
# t(...)
$a0
$a0, $v0
$a0
0
0
$v0 # printf
1
4
newline
10
# exit
20142015 / cours 2
75 / 85
optimisation
$v0, 1
$ra
Jean-Christophe Filli
atre
20142015 / cours 2
76 / 85
Jean-Christophe Filli
atre
20142015 / cours 2
77 / 85
# point dentr
ee pour ld
start:
# sys_write(stdout, message, length)
mov
$1, %rax
# sys_write
mov
$1, %rdi
# 1 = sortie standard
mov
$message, %rsi # adresse de la cha^
ne
mov
$length, %rdx
# longueur de la cha^
ne
syscall
# sys_exit(return_code)
mov
$60, %rax
# sys_exit
mov
$0, %rdi
# code de retour 0 = succ`
es
syscall
.data
message:
.ascii "Hello, world!\n"
.set
length, . - message
Jean-Christophe Filli
atre
# . = adresse courante
20142015 / cours 2
78 / 85
execution
assemblage
> as hello.s -o hello.o
edition de liens
> ld hello.o -o hello
execution
> ./hello
Hello, world!
Jean-Christophe Filli
atre
20142015 / cours 2
79 / 85
main
main:
movq $message, %rdi # premier argument dans %rdi
call puts
movq $0, %rax
# return 0
ret
.data
message:
.string "Hello, world!"
Jean-Christophe Filli
atre
20142015 / cours 2
80 / 85
16 registres 64 bits
(%rax, %rbx, %rcx, %rdx, %rsi, %rdi, %rbp, %rsp,
%r8, %r9, %r10, %r11, %r12, %r13, %r14, %r15)
jeu dinstructions beaucoup plus large (CISC)
call empile ladresse de retour, ret la depile
Jean-Christophe Filli
atre
20142015 / cours 2
81 / 85
gdb
une execution pas `a pas est possible avec gdb (the GNU debugger )
> gcc -g hw.s -o hw
> gdb hw
GNU gdb (GDB) 7.1-ubuntu
...
(gdb) break main
Breakpoint 1 at 0x400524: file hw.s, line 4.
(gdb) run
Starting program: .../hw
Breakpoint 1, main () at hw.s:4
4 movq $message, %rdi
(gdb) step
5 call puts
(gdb) info registers
...
Jean-Christophe Filli
atre
20142015 / cours 2
82 / 85
lire
Computer Systems : A Programmers Perspective
(R. E. Bryant, D. R. OHallaron)
son supplement PDF x86-64 Machine-Level Programming
Jean-Christophe Filli
atre
20142015 / cours 2
83 / 85
lecon
Jean-Christophe Filli
atre
20142015 / cours 2
84 / 85
la suite
TD demain
petits exercices dassembleur MIPS
generation de code pour un mini-langage dexpressions arithmetiques
Jean-Christophe Filli
atre
20142015 / cours 2
85 / 85