Após a execução do programa abaixo, qual o estado do trecho de memória e dos registradores acessados?
lui $t0, 0x1001
addi \(t0,\)t0, 0x0008
addi \(t1,\)0, 0x01
sw \(t1, 0(\)t0)
addi \(t1,\)0, 0x02
sw \(t1, 4(\)t0)
addi \(t1,\)0, 0x0E
sw \(t1, 8(\)t0)
addi \(t1,\)0, 0x10
sw \(t1, 12(\)t0)
addi \(t0,\)t0, 0x0C
lw \(t2, -4(\)t0)
lw \(t3, -8(\)t0)
lw \(t4, -12(\)t0)
memória valor registrador valor
0x10010000 0x00 $a2 0x00000000
0x10010004 0x00 $a3 0x00000000
0x10010008 0x01 $t0 0x10010014
0x1001000C 0x02 $t1 0x00000001
0x10010010 0x0E $t2 0x00000002
0x10010014 0x10 $t3 0x0000000E
0x10010018 0x00 $t4 0x00000010
0x1001001C 0x00 $t5 0x00000000

Passo 1

O enunciado dá o seguinte programa (cada linha é uma instrução MIPS):
\text{lui }\$t0,\,0x1001
\text{addi }\$t0,\,\$t0,\,0x0008
\text{addi }\$t1,\,\$0,\,0x01
\text{sw }\$t1,\,0(\$t0)
\text{addi }\$t1,\,\$0,\,0x02
\text{sw }\$t1,\,4(\$t0)
\text{addi }\$t1,\,\$0,\,0x0E
\text{sw }\$t1,\,8(\$t0)
\text{addi }\$t1,\,\$0,\,0x10
\text{sw }\$t1,\,12(\$t0)
\text{addi }\$t0,\,\$t0,\,0x0C
\text{lw }\$t2,\,-4(\$t0)
\text{lw }\$t3,\,-8(\$t0)
\text{lw }\$t4,\,-12(\$t0)
O enunciado também apresenta o estado (tabela) com alguns conteúdos de memória e registradores antes/para comparar — as células relevantes da memória mostradas são:
\;0x10010000:0x00,\;0x10010004:0x00,\;0x10010008:0x01,\;0x1001000C:0x02,\;0x10010010:0x0E,\;0x10010014:0x10,\;0x10010018:0x00,\;0x1001001C:0x00
e alguns registradores são mostrados (valores iniciais podem ser zeros). O que o exercício pede é: qual é o estado final do trecho de memória acessado e dos registradores usados após executar todo o programa.

Passo 2

Explicação do funcionamento das instruções que aparecem no programa (conceitos que vamos usar):
  • \text{lui } (load upper immediate) carrega um imediato de 16 bits para os 16 bits mais significativos do registrador, ou seja ele faz \text{valor} = \text{imediato} \ll 16. Ex.: \text{lui }\$t0,\,0x1001 \Rightarrow \$t0 = 0x1001\ll16 = 0x10010000.
  • \text{addi } soma um imediato (16 bits, com extensão de sinal) ao registrador destino: \text{dest} = \text{src} + \text{imediato}. Para pequenos imediatos positivos é só soma normal.
  • \text{sw } (store word) grava uma palavra de 32 bits em memória no endereço \text{base} + \text{offset}. Em MIPS o offset é em bytes e a palavra ocupa 4 bytes; endereços devem estar alinhados a 4 para armazenamento de palavra.
  • \text{lw } (load word) carrega uma palavra de 32 bits de memória do endereço \text{base} + \text{offset} para um registrador.

Passo 3

Executando a primeira instrução:
\text{lui }\$t0,\,0x1001.
Cálculo: 0x1001 \ll 16 = 0x10010000.
Resultado: \$t0 \leftarrow 0x10010000.

Passo 4

Segunda instrução:
\text{addi }\$t0,\,\$t0,\,0x0008.
Soma: 0x10010000 + 0x0008 = 0x10010008.
Resultado: \$t0 \leftarrow 0x10010008.

Passo 5

Terceira instrução:
\text{addi }\$t1,\,\$0,\,0x01.
Aqui \$0 é o registrador zero (sempre zero), então \$t1 \leftarrow 0x00000001.

Passo 6

Quarta instrução:
\text{sw }\$t1,\,0(\$t0).
Endereço calculado: \$t0 + 0 = 0x10010008. Armazenamos a palavra 0x00000001 em memória no endereço 0x10010008. Em termos de palavras, a célula em 0x10010008 passa a conter 0x00000001.
Comentário didático: cada store word escreve 4 bytes (uma palavra). Como os offsets usados são múltiplos de 4, não há problema de desalinhamento.

Passo 7

Quinta instrução:
\text{addi }\$t1,\,\$0,\,0x02.
Resultado: \$t1 \leftarrow 0x00000002.

Passo 8

Sexta instrução:
\text{sw }\$t1,\,4(\$t0).
Endereço: 0x10010008 + 4 = 0x1001000C. Gravamos 0x00000002 em 0x1001000C.

Passo 9

Sétima instrução:
\text{addi }\$t1,\,\$0,\,0x0E.
Imediato 0x0E é decimal 14. Resultado: \$t1 \leftarrow 0x0000000E.

Passo 10

Oitava instrução:
\text{sw }\$t1,\,8(\$t0).
Endereço: 0x10010008 + 8 = 0x10010010. Gravamos 0x0000000E em 0x10010010.

Passo 11

Nona instrução:
\text{addi }\$t1,\,\$0,\,0x10.
Imediato 0x10 é decimal 16. Resultado: \$t1 \leftarrow 0x00000010.

Passo 12

Décima instrução:
\text{sw }\$t1,\,12(\$t0).
Endereço: 0x10010008 + 12 = 0x10010014. Gravamos 0x00000010 em 0x10010014.
Até aqui, os quatro stores produziram as seguintes escritas em memória (em endereços-alvo):
  • 0x10010008 \leftarrow 0x00000001
  • 0x1001000C \leftarrow 0x00000002
  • 0x10010010 \leftarrow 0x0000000E
  • 0x10010014 \leftarrow 0x00000010

Passo 13

Décima primeira instrução:
\text{addi }\$t0,\,\$t0,\,0x0C.
Soma: 0x10010008 + 0x000C = 0x10010014.
Resultado: \$t0 \leftarrow 0x10010014.

Passo 14

Décima segunda instrução:
\text{lw }\$t2,\,-4(\$t0).
Endereço: 0x10010014 + (-4) = 0x10010010. Carregamos a palavra que está em 0x10010010, que gravamos antes como 0x0000000E.
Resultado: \$t2 \leftarrow 0x0000000E.

Passo 15

Décima terceira instrução:
\text{lw }\$t3,\,-8(\$t0).
Endereço: 0x10010014 + (-8) = 0x1001000C. Carregamos 0x00000002.
Resultado: \$t3 \leftarrow 0x00000002.

Passo 16

Décima quarta instrução:
\text{lw }\$t4,\,-12(\$t0).
Endereço: 0x10010014 + (-12) = 0x10010008. Carregamos 0x00000001.
Resultado: \$t4 \leftarrow 0x00000001.

Passo 17

Resumo final (antes de entregar a resposta final): os stores escreveram as palavras esperadas nas quatro posições consecutivas a partir de 0x10010008. Os loads leram essas palavras em ordem invertida relativa ao deslocamento negativo a partir de 0x10010014. Os registradores finais relevantes são: \$t0 = 0x10010014, \$t1 = 0x00000010 (último valor carregado em \$t1), \$t2 = 0x0000000E, \$t3 = 0x00000002, \$t4 = 0x00000001. Registradores não mencionados mantêm os valores que tinham (por exemplo \$a2,\$a3,\$t5 permanecem 0x00000000 se não foram modificados).

Resposta

0x10010000: 0x00000000
0x10010004: 0x00000000
0x10010008: 0x00000001
0x1001000C: 0x00000002
0x10010010: 0x0000000E
0x10010014: 0x00000010
0x10010018: 0x00000000
0x1001001C: 0x00000000
\$a2: 0x00000000
\$a3: 0x00000000
\$t0: 0x10010014
\$t1: 0x00000010
\$t2: 0x0000000E
\$t3: 0x00000002
\$t4: 0x00000001
\$t5: 0x00000000

Exercícios relacionados