Professional Documents
Culture Documents
CM Mips
CM Mips
ASSEMBLER DIRECTIVES
.data [addr]∗ Subsequent items are stored in the data segment
.kdata [addr]∗ Subsequent items are stored in the kernel data segment
.ktext [addr]∗ Subsequent items are stored in the kernel text segment
.text [addr]∗ Subsequent items are stored in the text
∗
starting at [addr] if specified
.ascii str Store string str in memory, but do not null-terminate it
.asciiz str Store string str in memory and null-terminate it
.byte b1 , . . . , bn Store the n values in successive bytes of memory
.double d1 , . . . , dn Store the n floating-point double precision numbers in successive memory locations
.float f1 , . . . , f1 Store the n floating-point single precision numbers in successive memory locations
.half h1 , . . . , hn Store the n 16-bit quantities in successive memory halfwords
.word w1 , . . . , wn Store the n 32-bit quantities in successive memory words
.space n Allocate n bytes of space in the current segment
.extern symsize Declare that the datum stored at sym is size bytes large and is a global label
.globl sym Declare that label sym is global and can be referenced from other files
.align n Align the next datum on a 2n byte boundary, until the next .data or .kdata directive
.set at Tells SPIM to complain if subsequent instructions use $at
.set noat prevents SPIM from complaining if subsequent instructions use $at
ALU registres
Mémoire vive (RAM)
Unité de contrôle
CPU Périphériques
RAM
— Elle contient les données et les programmes, sous forme numérique
— Un chiffre binaire (0 ou 1) s’appelle un bit (binary digit)
— Découpée par blocs de 8 bits. Un bloc de 8 bits = un octet
— Dans la RAM, chacun des octets est indexé par un numéro : son adresse
registres
— chaque registre = 1 mémoire de 32 bits = 1 mot = 4 octets
— Registres spéciaux :
— CP : Compteur de Programme = adresse de l’instruction suivante
— RI : Registre d’Instruction = instruction courante
— 32 registres programmables accessibles par leur numéro ($0 à $31) ou leur nom
(cas particulier : $0 contient toujours la valeur 0 — son nom est $zero)
Langage MIPS
— Fichier texte = programme
— Etape d’assemblage → programme binaire chargé en mémoire
— .data
directive démarrant la zone mémoire réservée aux données
— .text
directive démarrant la zone mémoire réservée au programme
Dans la zone .text, chaque ligne correspond à une instruction du programme, et sera traduite par un
mot (32 bits) par l’assembleur.
Addition et soustraction
— opérandes et résultat sont des registres (pas d’accès à la RAM)
— Syntaxe des instructions : toujours de la forme
op rd, rs, rt
add $v0, $s0, $s1 # stocke dans $v0 la somme des contenus de $s0 et de $s1
add $2 , $16, $17 # pareil, en désignant les registres par leur numéro
sub $t1, $t2, $t3 # stocke dans $t1 la différence ($t2 - $t3)
addu $v0, $s0, $s1 # comme add, sans plantage si dépassement
subu $t1, $t2, $t3 # comme sub, sans plantage si dépassement
— version avec « immediate » (constante) : le second opérande est un immédiat au lieu d’être le contenu
d’un registre
Exercice 1. Programmer en mips les calculs suivants (le résultat devra se trouver dans $v0) :
— 900
— 19 + 98
— (19 + 91) − (28 + 82)
op rt, offset(rs)
label1:
un_nom_de_label_quelconque:
la rd, label
.data
label_octets: .byte -1, 30, -1 # trois octets (-1, 30, -1)
label_mots: .word 1900, 123 # deux mots (1900, 123) (← huit octets)
.text
la $s0, label_octets # charge l'adresse label_octets dans $s0
lb $t1, 0($s0) # charge -1 dans le registre $t1
lb $t2, 1($s0) # charge 30 dans le registre $t2
lbu $t3, 2($s0) # charge 255 dans le registre $t3
la $s1, label_mots # charge l'adresse label_mots dans $s1
lw $t4, 0($s1) # charge 1900 dans $t4
lw $t5, 4($s1) # charge 123 dans $t5
sb $t2, 0($s1) # stocke l'octet 30 dans la RAM (à label_mots)
sw $t4, 0($s0) # stocke le mot 1900 en RAM (à label_octets)
Exercice 2. Faire un programme qui calcule res = 2a + b, où a, b et res sont des labels dans la
zone .data, désignant chacun un mot de valeur initiale respective 950, 123 et 0.
Branchements
— Branchement si égaux
Exercice 4. Faire un programme qui transforme le mot stocké au label blip en sa valeur absolue.
Algorithme :
1. initialisation : $s1 ← a , $s2 ← 0
2. tant que $s1 >= b, mettre à jour :
$s1 ← $s1 - b
$s2 ← $s2 + 1
3. terminaison : quotient ← $s2, reste ← $s1
Entrées / Sorties
— Voir la partie SYSCALLS de la feuille de référence.
Exemples :
.data
chaine: .asciiz "ab12" # 5 octets : 97, 98, 49, 50, 0
octets: .byte 97, 98, 49, 50, 0 # 5 octets : 97, 98, 49, 50, 0
espace: .space 200 # 200 octets non initialisés
.text
addi $v0, $0, 1 # code de syscall : 1 = print_int
addi $a0, $0, 199 # argument de syscall : 199
syscall # → affiche 199 à l'écran
addi $v0, $0, 4 # code de syscall : 4 = print_string
la $a0, octets # argument de syscall : adresse octets
syscall # → affiche ab12 à l'écran
addi $v0, $0, 8 # code de syscall : 8 = read_string
la $a0, espace # arg1 de syscall : adresse espace
addi $a1, $0, 200 # arg2 de syscall : 200
syscall # lit une chaîne de caractères au clavier
# (jusqu'à Entrée ou au max 200 caractères)
# et stocke les codes ascii (octets)
# à partir du label "espace"
Sous-programmes
variables i, j, k
... | MIPS : on suppose que
k ← mult(i,j) # mult = algorithme paramétré | « mult » est le label
j ← mult(k,k) # qui « renvoie » un résultat | d'un code
i ← i + j # | effectuant la multiplication
Problèmes :
— comment passer des arguments
— comment récupérer le résultat
— à la fin de l’exécution de « mult », vers quelle adresse faire le saut de « retour » ? (dépend de l’adresse
du saut « aller »)
— mult peut modifier le contenu des registres, or on a besoin de conserver la valeur de i pour l’addition
finale
1012 jal label # jal : 1. place l'adresse de retour (1016) dans $ra
1016 ... # 2. place l'adresse « label » dans CP (i.e. saut)
jr $ra
Exemple :
— L’adresse de retour de l’appel initial de mrec a été placée dans $ra, mais cette valeur va être écrasée
par l’adresse ret dès le premier appel récursif.
— Il est donc nécessaire de sauvegarder l’adresse de retour de mrec avant l’appel récursif.
Utilisation de la pile
mrec: addi $sp, $sp, -4 # empiler $ra jpos: addi $a1, $a1, -1 #
sw $ra, 0($sp) jal mrec # mrec(i,j-1)
bne $a1, $0, jpos add $v0, $v0, $a0 # $v0 + i
add $v0, $0, $0 # si $a1 = 0, ret: lw $ra, 0($sp) # dépiler $ra
j ret # aller en ret addi $sp, $sp, 4 # restituer $sp
jr $ra