Non abbiamo bisogno di una PSP per testare il codice

Transcript

Non abbiamo bisogno di una PSP per testare il codice
SPIM e MIPS
Non abbiamo bisogno di una PSP per testare il codice
Michele “Jazzinghen” Bianchi
Interessi: Game Design, Embedded Systems
eMail: [email protected]
Webpage: http://disi.unitn.it/~bianchi
Ricevimento: Mi mandate una mail e ci
mettiamo d’accordo
● Non avete capito qualcosa? Fatemi
domande subito, sono quì apposta.
●
●
●
●
SPIM (o meglio QtSpim)
MIPS è un assembly che
viene implementato in
piattaforme embedded
e…
La PS1, la PS2 e la PSP! (E
l’ho scoperto solo ieri!)
Vabbeh, ma comunque:
LOL INTEL
Rimane comunque il fatto che il nostro PC non
è in grado di interpretare MIPS.
Per risolvere questo installeremo un
emulatore con alcune funzionalità simili ad un
debugger
L’url del sito è: http://spimsimulator.sourceforge.
net/
Il resto sapete come farlo.
Scaricare + Installare QtSpim
QtSPIM - Un overview
Scrivere codice in SPIM (a.k.a. IDE WARS)
Machissenefrega!
Iniziamo subito a fare cose.
● Il metodo migliore per
capire una cosa è farla.
● Proveremo dalla cosa
più banale che avete
visto a
Programmazione 1, il
BUBBLE SORT!
Il Bubble Sort
● Per rinfrescarci la memoria, è quell’
algoritmo di ordinamento che gira in O(n2),
continuando a scambiare posto ai valori se
sono nell’ordine sbagliato.
● Da non confondere con lo Shaker Sort, dove
si fanno passaggi andata e ritorno.
#include "stdint.h"
#include "stdlib.h"
#include "stdio.h"
void sort (int32_t * v, uint16_t len){
int32_t i,j;
void swap (int32_t * v, uint32_t k){
int32_t tmp;
tmp = v[k];
v[k] = v[k+1];
v[k+1] = tmp;
}
for (i = 0; i < len; i++){
for (j = i - 1; j >= 0 &&
v[j] > v[j+1]; j--){
swap(v, j);
}
}
}
Codice in C - Parte 1
int main (int argc, char **argv){
int32_t i;
int32_t data[10] = {-37, 190, 214, -41, -65, 242, -62, 13, 197, 10};
sort(data, 10);
printf("Array: %d", data[0]);
for (i=1; i < 10; i++){
printf(", %d", data[i]);
}
printf(".\n");
return 0;
}
Codice in C - Parte 2
swap:sll
$t1, $a1, 2
add $t1, $a0, $t1
# $t1 = k * 4
# $t1 = v + (k * 4) {$t1 = &v[k]}
lw
lw
$t0, 0($t1)
$t2, 4($t1)
# $t0 = v[k] {temp = v[k]}
# $t2 = v[k+1]
sw
sw
$t2, 0($t1)
$t0, 4($t1)
# v[k] = $t2 {v[k+1]}
# v[k+1] = temp
jr
$ra
# "Return"
Codice in MIPS - SWAP
sort:
addi $sp, $sp, -20
sw
$ra, 16($sp)
sw
$s3, 12($sp)
sw
$s2, 8($sp)
sw
$s1, 4($sp)
sw
$s0, 0($sp)
move $s2, $a0
move $s3, $a1
move $s0, $zero
# Allocate 5 places in the stack
# $s2 = v
# $s3 = len
# i = 0
Codice in MIPS - SORT (Initialisation)
for1st:
for2st:
exit2:
slt
beq
$t0, $s0, $s3
$t0, $zero, exit1
# if (i >= len) {$t0 = 0}
# if ($t0 == 0) {goto exit1}
addi
$s1, $s0, -1
# j = i-1;
slti
bne
$t0, $s1, 0
$t0, $zero, exit2
# if (j >= 0) {$t0 = 0}
# if ($t0 != 0) {goto exit2}
sll
add
lw
lw
slt
beq
$t1,
$t2,
$t3,
$t4,
$t0,
$t0,
#
#
#
#
#
#
move
move
$a0, $s2
$a1, $s1
# First argument = v
# Second argument = j
jal
swap
# Call swap(v, j)
addi
j
$s1, $s1, -1
for2st
# j-# Back at start of "j-for"
addi
j
$s0, $s0, 1
for1st
# i++
#
$s1, 2
$s2, $t1
0($t2)
4($t2)
$t4, $t3
$zero, exit2
$t1 = j * 4
Compute &v[j]
$t3 = v[j]
$t4 = v[j+1]
if ($t4 < $t3) {$t0 = 1}
if ($t0 == 0) {goto exit2}
Back at start of "i-for"
Codice in MIPS - SORT (For)
exit1:
lw
lw
lw
lw
lw
addi $sp,
$s0,
$s1,
$s2,
$s3,
$ra,
$sp,
jr
$ra
0($sp)
4($sp)
8($sp)
12($sp)
16($sp)
20
# Restore return address
# Restore Stack Pointer
# "Return"
Codice in MIPS - SORT (Exit)
.data
datarr:
.word-37, 190, 214, -41, -65, 242, -62, 13, 197, 10
.text
main:la
add
jal
$a0, datarr
$a1, $zero, 10
sort
nop
nop
# Load address for array
# Set array length to 10
# Call sort(data, 10)
# General Breakpoints
# ...
# Le altre due chiamate quì sotto...
Codice in MIPS - MAIN + DATA
UFF...
È stata dura, ma se fate girare il programma in
Assembly MIPS in QtSPIM e quello in C, dopo
averlo passato per bene con le vostre skills da
GCC HAXORZ vedrete che il risultato è lo stesso*
* In C viene stampato a video, in QtSPIM viene modificato l’array nella sezione .data
Una cosa, ladies and
gentlemen...
Il libro, nella sua tabella riassuntiva delle
istruzioni fa DI TUTTO per essere
confusionario (IMHO). La cosa da ricordare è:
OP rd, rs, rt
Non sapete quante volte ho fatto casino con l’
operatore slt.
Un esercizio:
Vettori vs. Puntatori
● Per fare gli esercizi di Assembly è
NECESSARIO che sappiate come funzionano
i puntatori.
● Per iniziare proveremo a fare un esercizio
dove dovrete inizializzare due vettori a 0
usando o l’accesso ai vettori o l’aritmetica
dei puntatori.
void zeroes_vec (int32_t *vec, uint32_t len){
uint32_t i;
for (i = 0; i < len; i++){
vec[i] = 0;
}
}
void zeroes_point (int32_t *vec, uint32_t len){
int32_t *p;
for (p = vec; p < &vec[len]; p++){
*p = 0;
}
}
LOL PUNTATORI! - Il Codice in C
Try despair...
(Non vi preoccupate, non sapevo neanche io cosa stavo facendo la prima volta.)
OK, buon lavoro.
.data
datarr:
datarr2:
.word
-37, 190, 214, -41, -65, 242, -62, 13, 197, 10
.word -37, 190, 214, -41, -65, 242, -62, 13, 197, 10
.text
main:
la
add
$a0, datarr
$a1, $zero, 10
# Load address for array
# Set array length to 10
jal
vecz
# Call vecz(data, 10)
la
$a0, datarr2
# Load address for second array
poiz
# Call poiz(data2, 10)
nop
jal
nop
nop
# General Breakpoints
# ...
MGSV: Ground ZEROES - La Soluzione I
vecz:
vecfor: sll
move
$t0, $zero
$t1, $t0, 2
add
$t2, $a0, $t1
sw
$zero, 0($t2)
addi
$t0, $t0, 1
slt
$t2, $t0, $a1
bne
$t2, $zero, vecfor
jr
poiz:
poifor: sll
$ra
move
$t0, $a0
$t1, $a1, 2
add
$t1, $a0, $t1
sw
$zero, 0($t0)
addi
$t0, $t0, 4
slt
$t2, $t0, $t1
bne
$t2, $zero, poifor
jr
# i = 0
# $t0 = i * 4
# $t2 = &vec[i]
# vec[i] = 0
# i++
# if (i < len) {$t2 = 1}
# if ($t2 != 0) {goto vecfor}
# p = vec
# $t1 = len * 4
# $t1 = &vec[len]
# *p = 0
# p++
#
if (p < &vec[len]) {$t2 = 1}
# if ($t2 != 0) {goto poifor}
$ra
ZEROES - La Soluzione II
Vi sentite già più tipo Gandalf Ed?
Fine, mi sa...
Ora delle domande!