Laboratori 1: Introducció al simulador RARS
Lliuraments
Cal lliurar les respostes als exercicis següents al campus virtual abans de l’inici de la sessió de laboratori:
| Exercici | Nom i format del fitxer |
|---|---|
| Exercici 28.1 | s1_2_1.md |
| Exercici 28.2 | s1_2_2.md |
| Exercici 28.3 | s1_3_1.md |
| Exercici 28.4 | s1_3_2.md |
| Exercici 28.5 | s1_4_1.md |
| Exercici 28.6 | s1_5_1.s i s1_5_1.md |
| Exercici 28.7 | s1_5_2.s i s1_5_2.md |
Lectura prèvia
Per fer la sessió, cal haver instal·lat RARS tal com s’indica a la Presentació del curs.
També cal haver llegit i entès els continguts següents:
| Concepte | On trobar-ho |
|---|---|
| Format del codi assemblador | EC 2.7 |
| Esquelet d’un programa | RISC-V 2.19 |
Accessos a memòria (lw), desplaçaments (slli) i salts condicionals (bge, blt) |
Secció 2.6.3.1, Secció 3.1.1, Secció 3.4.1 |
Pseudoinstruccions la i li, i l’expansió de la en auipc + addi |
RISC-V 2.17, RISC-V 2.16, RISC-V 2.14 |
Es recomana seguir el format del codi (EC 2.7) i l’esquelet (RISC-V 2.19) en tots els programes lliurats al laboratori i a l’examen de laboratori, com fan els exemples. El format no s’avalua per si mateix.
28.1 El primer programa
El Codi 28.1 és un programa mínim executable a RARS: imprimeix un missatge per consola i en finalitza l’execució.
Per executar-lo a RARS:
- Copieu el codi a l’editor de RARS i guardeu-lo com
hola.s. - Assembleu amb Run → Assemble (o F3). Si hi ha errors, RARS els mostra al panell de missatges amb el número de línia.
- Executeu amb Run → Go (o F5). El missatge ha d’aparèixer al panell de consola.
Una crida al sistema és una petició de servei al sistema operatiu (o, en el cas de RARS, al simulador). Es fa carregant el codi de servei a a7 i els paràmetres a a0–a2, i executant ecall. Les crides al sistema s’estudien en detall a Secció 9.5; per ara n’hi ha prou amb usar-les com a patró:
Codi de servei (a7) |
Servei | Paràmetre (a0) |
Retorn (a0) |
|---|---|---|---|
| 1 | print_int |
enter a imprimir | — |
| 4 | print_string |
adreça de la cadena | — |
| 93 | exit2 |
codi de sortida | — |
28.2 Exploració del simulador
La secció treballa sobre el programa suma.s, que calcula la suma dels elements d’un vector d’enters i deixa el resultat al registre t0.
suma.s
.data
V: .word -1, -2, -3, -4, -5, -6, -7, -8, -9, -10
.text
li t0, 0 # t0 = suma = 0
li t1, 0 # t1 = i = 0
li t2, 10 # t2 = N = 10
la t3, V # t3 = adreça de V
bucle:
bge t1, t2, fi # si i >= N, surt
slli t4, t1, 2 # t4 = 4*i
add t4, t3, t4 # t4 = @V[i]
lw t4, 0(t4) # t4 = V[i]
add t0, t0, t4 # suma += V[i]
addi t1, t1, 1 # i++
j bucle
fi:
li a7, 93
li a0, 0
ecallUn cop assemblat el programa (F3), la pestanya Execute mostra els panells que s’usaran durant la simulació:
- Panell de codi desassemblat (Text Segment, esquerra): mostra les instruccions en memòria, una per fila, amb l’adreça, la codificació en hexadecimal i el mnemònic. La instrucció que s’executarà a continuació apareix ressaltada.
- Panell de registres (Registers, dreta): mostra el contingut dels 32 registres de propòsit general i el PC. Els registres modificats a l’últim pas apareixen ressaltats.
- Panell de memòria de dades (Data Segment, centre-baix): mostra el contingut del segment
.dataen format de paraules hexadecimals. - Panell de consola (Run I/O, baix): mostra la sortida de les crides al sistema i permet introduir dades.
Exercici 28.1 (s1_2_1.md) Assembleu suma.s i responeu les preguntes següents:
- On es mostra el valor del comptador de programa (program counter, PC)?
- RARS no mostra el nombre d’instruccions executades als panells principals. Quina eina de RARS permet comptar-les? Indiqueu el camí de menús per obrir-la i el pas necessari perquè comenci a comptar.
- El panell de codi mostra, per a cada instrucció, tres columnes de valors (a més de la casella d’activació de punt de ruptura i la columna de codi font). Quina informació conté cadascuna?
Solució 28.1.
- Al panell de registres (Registers), a la fila
pc. - Tools → Instruction Counter. Cal obrir-la abans d’executar el programa i prémer Connect to Program perquè comenci a comptar; si s’executa el programa abans de connectar l’eina, el recompte no es registrarà.
- Address (adreça de memòria de la instrucció), Code (codificació de la instrucció en hexadecimal) i Basic (la instrucció real, amb els registres identificats amb
x0–x31).
Exercici 28.2 (s1_2_2.md) Algunes pseudoinstruccions s’expandeixen en més d’una instrucció real. Treballeu sobre suma.s ja assemblat.
- Localitzeu la pseudoinstrucció
la t3, Val panell de codi desassemblat. Quines instruccions reals ha generat? Copieu-les exactament tal com apareixen al panell. - Per quina raó
lanecessita dues instruccions reals en lloc d’una? - La pseudoinstrucció
li t2, 10, en canvi, genera una sola instrucció. Per quina raó en aquest cas n’hi ha prou amb una? Hauria passat el mateix ambli t2, 100000?
Indicació: els immediats de les instruccions tipus I tenen 12 bits amb signe (rang −2048..2047).
Solució 28.2.
- El panell mostra
auipc x28,0x0000fc10seguida d’addi x28,x28,0xfffffff4, és a dir,auipc t3, 0xfc10iaddi t3, t3, -12amb els noms ABI (els valors exactes depenen de l’adreça deVi de la posició delaal programa; l’estructura auipc+addi és sempre la mateixa). - Perquè una adreça de memòria ocupa 32 bits, i cap instrucció tipus I té un immediat de 32 bits:
auipcaporta els 20 bits alts (relatius al PC) iaddihi suma els 12 bits baixos amb signe. 10cap dins el rang [−2048, 2047] d’un immediat de 12 bits amb signe, per tant, una solaaddin’hi ha prou. Ambli t2, 100000no passaria el mateix: 100000 no cap en 12 bits, de manera que RARS generarialui t2, 0x18seguida d’addi t2, t2, 1696(dues instruccions), igual que ambla.
28.3 Execució i inspecció
RARS ofereix tres modes d’execució:
- Execució contínua (F5): executa el programa fins al final (o fins al primer punt de ruptura).
- Execució pas a pas (F7): executa una instrucció i s’atura. Útil per seguir el flux instrucció per instrucció.
- Reinici (F12): torna el programa a l’estat inicial sense tornar a assemblar.
El programa hola.s de Secció 28.1 no té bucles: el nombre d’instruccions és fix i petit. És el programa que s’usarà per al recompte manual.
Exercici 28.3 (s1_3_1.md) Treballeu sobre el programa hola.s.
- Obriu Tools → Instruction Counter, connecteu-la al programa (Connect to Program) i executeu amb F5. Quin nombre d’instruccions executades reporta l’eina?
- Feu el recompte manual: llisteu totes les instruccions que s’executen, en ordre, indicant per a cada una si és una instrucció real o l’expansió d’una pseudoinstrucció. Quantes instruccions reals s’executen en total?
- El valor del recompte manual coincideix amb el que reporta l’Instruction Counter? Si hi ha diferència, expliqueu-ne la causa.
Indicació: la pseudoinstrucció la s’expandeix en dues instruccions reals. Useu el panell de codi desassemblat per veure exactament quines instruccions s’executen.
Solució 28.3.
- 7 instruccions.
la a0, msg(auipc + addi, 2 instruccions reals),li a7, 4(addi, 1),ecall(1),li a7, 93(addi, 1),li a0, 0(addi, 1),ecall(1). Total: 7 instruccions reals.- Sí, coincideixen (7 = 7). Tot i que el codi font té 6 instruccions, el recompte manual dona 7 perquè
las’expandeix en dues instruccions reals.
Exercici 28.4 (s1_3_2.md) Assembleu suma.s i observeu el panell de memòria de dades.
- En quina adreça de memòria comença el vector
V? - En quina adreça exacta es troba
V[3]? Quin és el seu contingut en hexadecimal? V[0]conté el valor-1. Quin valor hexadecimal té al panell de memòria? Expliqueu com s’obté aquesta representació.- El panell mostra cada paraula com un valor hexadecimal de 32 bits. Quin ordre dels bytes (endianness) usa RV32I?
Solució 28.4.
0x10010000(adreça per defecte del segment.dataa RARS).0x1001000C(= 0x10010000 + 3·4); conté0xFFFFFFFC.0xFFFFFFFF. S’obté aplicant a +1 la regla del canvi de signe en Ca2 (Secció 1.5.1): es complementen tots els bits d’1 (0x00000001→0xFFFFFFFE) i se suma 1; o, de manera equivalent, \(2^{32} - 1\) =0xFFFFFFFF.- RV32I és little-endian: el byte de menys pes s’emmagatzema a l’adreça més baixa.
28.4 Punts de ruptura
Un punt de ruptura (breakpoint) és una marca sobre una instrucció que fa que l’execució contínua (F5) s’aturi just abans d’executar-la. S’activa i es desactiva fent clic a la casella de l’esquerra del panell de codi desassemblat, a la fila de la instrucció triada.
Els punts de ruptura permeten inspeccionar l’estat del programa en un punt clau sense haver d’executar-lo pas a pas des del principi. Quan el programa s’atura, es pot continuar amb F5 (fins al següent punt de ruptura) o amb F7 (pas a pas).
Exercici 28.5 (s1_4_1.md) Treballeu sobre suma.s.
- Afegiu un punt de ruptura a la instrucció
add t0, t0, t4(la que acumula la suma). Executeu el programa amb F5. En quina iteració s’atura? Quins són els valors det0it4en aquest moment? Tingueu en compte que l’execució s’atura just abans d’executar la instrucció marcada. - Premeu F5 repetidament fins al final. Anoteu el valor de
t4en cada aturada. Verifiqueu que els valors corresponen als elements del vectorVen ordre. - Quin és el valor final de
t0un cop ha acabat l’execució? Era el resultat esperat? Justifiqueu-lo.
Solució 28.5.
- S’atura a la primera iteració, amb
t0 = 0it4 = -1. - Els valors de
t4en cada aturada successiva són −1, −2, −3, −4, −5, −6, −7, −8, −9, −10: coincideixen exactament amb els elements deVen ordre. t0 = -55. És el resultat esperat: −1−2−3−4−5−6−7−8−9−10 = −55.
28.5 Depuració
Quan un programa assembla sense errors, però produeix un resultat incorrecte, cal depurar-lo: executar-lo pas a pas o amb punts de ruptura per identificar en quina instrucció el comportament no és l’esperat.
El procediment general és:
- Determineu el resultat esperat abans d’executar el programa.
- Identifiqueu un punt de control (per exemple, la instrucció d’acumulació d’un bucle) i afegiu-hi un punt de ruptura.
- En cada aturada, comproveu que els valors dels registres rellevants coincideixen amb el que s’esperava.
- Quan trobeu una discrepància, retrocediu un pas per identificar la instrucció causant. RARS ofereix Run → Backstep (F8) per desfer l’última instrucció executada sense haver de reiniciar.
Exercici 28.6 (s1_5_1.s i s1_5_1.md) El programa s1_5_1.s és una versió errònia del programa suma.s. Conté un únic error que fa que el resultat final de t0 no sigui -55.
s1_5_1.s
- Sense executar el programa, analitzeu el codi i preveieu quin serà el resultat incorrecte de
t0i per quina raó. - Executeu el programa pas a pas per confirmar la vostra predicció. En quina iteració s’observa per primera vegada un comportament incorrecte?
- Corregiu l’error (canvieu una única línia) i verifiqueu que el resultat és
-55. Lliureu la versió corregida coms1_5_1.s. - Al fitxer
s1_5_1.md, descriviu: quina és la instrucció errònia, quin valor incorrecte produïa i com ho heu detectat.
Solució 28.6.
- L’error és
li t1, 9(hauria de serli t1, 0): l’índexicomença a 9 en lloc de 0, per tant, el bucle només sumaV[9] = -10. El resultat incorrecte previst ést0 = -10. - El comportament incorrecte s’observa ja a la primera iteració:
t1val 9 des de l’inici i at4es llegeixV[9] = -10en lloc deV[0] = -1. - Cal canviar
li t1, 9perli t1, 0. Amb la correcció,t0acaba valent-55. - La instrucció errònia és
li t1, 9; produïat0 = -10perquè només s’acumulava l’últim element del vector; es detecta comparant l’índex inicial esperat (0) amb el valor carregat at1a l’inici de l’execució pas a pas.
Exercici 28.7 (s1_5_2.s i s1_5_2.md) El programa s1_5_2.s calcula la mitjana entera dels elements del vector V (és a dir, la divisió entera de la suma entre el nombre d’elements). La divisió es fa per mitjà d’un segon bucle que resta repetidament el divisor del dividend mentre el dividend no sigui inferior al divisor.
El programa conté un únic error. El resultat correcte del quocient (registre t5) hauria de ser 5 (ja que \(\lfloor 55/10 \rfloor = 5\), i la suma dels elements de V = {1, 2, ..., 10} és 55).
s1_5_2.s
.data
V: .word 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
.text
li t0, 0 # t0 = suma = 0
li t1, 0 # t1 = i = 0
li t2, 10 # t2 = N = 10
la t3, V
bucle:
bge t1, t2, fi
slli t4, t1, 2
add t4, t3, t4
lw t4, 0(t4)
add t0, t0, t4
addi t1, t1, 1
j bucle
fi:
li t5, 0 # t5 = quocient = 0
mv t6, t2 # t6 = divisor = N
bucle2:
blt t0, t6, fi2 # si suma < divisor, acaba
sub t0, t6, t0 # suma -= divisor
addi t5, t5, 1
j bucle2
fi2:
li a7, 93
li a0, 0
ecall- Sense executar el programa, llegiu el codi del segon bucle (
bucle2) i identifiqueu l’error. Què hauria de fer la instrucció errònia? - Afegiu un punt de ruptura a la primera instrucció de
bucle2. Executeu fins al punt de ruptura amb F5 i comproveu quet0és55it6és10. - Continueu amb F7 pas a pas. Observeu el valor de
t0després de la instrucciósub. Es confirma el diagnòstic del punt a)? - Corregiu l’error i verifiqueu que
t5val5. Lliureu la versió corregida coms1_5_2.s. - Al fitxer
s1_5_2.md, descriviu: on heu col·locat el punt de ruptura i per quina raó, quina és la instrucció errònia i com l’heu corregit.
Solució 28.7.
- L’error és
sub t0, t6, t0(els operands estan invertits: hauria de sersub t0, t0, t6). La instrucció hauria de calculart0 = t0 - t6(suma restant el divisor), not6 - t0. - A l’aturada,
t0 = 55(suma deV = {1, ..., 10}) it6 = 10(còpia deN). - Després del
suberroni,t0 = 10 - 55 = -45. Això confirma el diagnòstic: en comptes de restar el divisor de la suma (55 − 10 = 45), es resta la suma del divisor, produint un valor negatiu que fa sortir del bucle massa aviat (ambt5 = 1en lloc de 5). - Amb
sub t0, t0, t6, el bucle itera 5 vegades (55→45→35→25→15→5) it5acaba valent5. - Exemple de resposta: el punt de ruptura es col·loca a
blt t0, t6, fi2(primera instrucció debucle2) perquè és el punt on es pot comprovar l’estat inicial det0it6abans de cap iteració; la instrucció errònia éssub t0, t6, t0, amb els operands invertits; es corregeix escrivintsub t0, t0, t6.