let rec fib n = if n <= 1 then 1 else fib (n-1) + fib (n-2) |
% xspim -notrap -file fib.spiLa démarche suggérée est d'écrire un programme en trois fonctions, read, write et fib. La fonction write est donnée dans le cours. La fonction read se déduit facilement de write (voir les appels système). La fonction fib se déduit de la fonction fact. Enfin le code de lancement appelle ces trois fonctions, ce code est étiquetté conventionnelle
__start
.
Vous aurez peut-être besoin de consulter la liste abrégée des
instructions voir le manuel SPIM.
let fib n = let prec = ref 1 and curr = ref 1 in for i = 2 to n do let save = !cur in cur := !prec + !cur ; prec := save done ; !cur |
# tar xf pgm.tar
# cd pgm # make zyva ocamllex lexer.mll 11 states, 267 transitions, table size 1134 bytes ocamlc expression.mli ... ocamlc -o zyva lexer.cmo parser.cmo arithmetique.cmo zyva.cmo Cannot find file arithmetique.cmo make: *** [zyva] Erreur 2C'est bien logique, il manque un bout de source important.
(* Compilateur proprement: compile e - Imprime le code qui réalise e sur la sortie standard *) val compile : Expression.expression -> unit |
# mv squelette.ml pgm/arithmetique.ml
# cd pgm # make zyva
(* Les quatre opérations *) type binop = Plus | Minus | Times | Div type expression = (* Opérations *) | Binexp of binop * expression * expression (* Entier *) | Int of int (* Variable *) | X |
x
».
# ./zyva < simple.exp > simple.spi
# spim -notrap -file simple.spi SPIM Version 6.3a of January 14, 2001 Copyright 1990-2000 by James R. Larus (larus@cs.wisc.edu). All Rights Reserved. See the file README for a full copyright notice. 3 3 4 4 0Bref, le code de lancement contient une boucle lire un entier x au clavier, calculer l'expression (ici c'est x), l'afficher. La boucle continue tant que la valeur lue est non nulle.
eval: move $v0, $a0 j $ra |
(x-1)*3 + x*x
», on devrait
alors sensiblement obtenir ce style de code machine
(en commentaire les instructions correspondantes pour un bytecode
« évident ») :
eval: move $v0, $a0 #VAR sub $sp,$sp, 4 #PUSH sw $v0, 0($sp) move $v0, $a0 #VAR lw $v1, 0($sp) add $sp,$sp, 4 #POP mul $v0, $v0, $v1 #MUL sub $sp,$sp, 4 #PUSH sw $v0, 0($sp) li $v0, 3 #CONST 3 sub $sp,$sp, 4 #PUSH sw $v0, 0($sp) li $v0, 1 #CONST 1 sub $sp,$sp, 4 #PUSH sw $v0, 0($sp) move $v0, $a0 #VAR lw $v1, 0($sp) add $sp,$sp, 4 #POP sub $v0, $v0, $v1 #SUB lw $v1, 0($sp) add $sp,$sp, 4 #POP mul $v0, $v0, $v1 #MUL lw $v1, 0($sp) add $sp,$sp, 4 #POP add $v0, $v0, $v1 #ADD j $ra |
let registers = [| "$v0" ; "$a1" ; "$a2" ; "$t0" ; |] (* tableau de quatre chaînes *) |
li r, i |
$a0
.move r, $a0 |
C(r, e1) C(r', e2) add r, r, r' |
(x-1)*3 + x*x
» on devrait obtenir plus ou
moins ceci :
move $v0, $a0 li $a1, 1 sub $v0, $v0, $a1 li $a1, 3 mul $v0, $v0, $a1 move $a1, $a0 move $a2, $a0 mul $a1, $a1, $a2 add $v0, $v0, $a1 |
$a1
, on a :
move $a1, $a0 move $a2, $a0 mul $a1, $a1, $a2 |
mul $a1, $a0, $a0 |
move $v0, $a0 li $a1, 1 sub $v0, $v0, $a1 |
sub $v0, $a0, 1 |
sub $v0, $a0, 1 mul $v0, $v0, 3 mul $a1, $a0, $a0 add $v0, $v0, $a1 |
li $v0, 1 add $v0, $v0, $a0 |
add $v0, $a0, 1 |
Ce document a été traduit de LATEX par HEVEA.