Exemplo 2 - Trabalhando com dados em memória
Detalhe importante: O acesso à memória do SPIM em nossos programas deve ser feito com valores acima da posicao inicial do global pointer (10008000h). Esta é a parte da memória do SPIM que iremos utilizar para armazenar nossos dados. Mais a frente veremos também como armazenar dados "constantes" de uma forma mais prática, sem a necessidade de utilizar as instruções de store.
Vamos fazer um exercício simples de acesso a memória:
Tendo-se um array de 100 elementos (words) que inicia no endereço de memória 5000 (em direção aos endereços crescentes) transfira este array para o endereço 6000.
Primeiro precisamos carregar na memória este array de elementos que foi considerado no enunciado. Como as posições de memória 5000 e 6000 estão fora da área que temos acesso na memória, utilizaremos o $gp (global pointer) + 5000 como endereço inicial do array fonte. Já para o array destino, utilizaremos o valor de $gp + 6000.
.text | |
.globl main | |
main: | |
move $s0,$gp | |
addi $s0,$s0,5000 | # Ponteiro para os dados do array fonte ($gp) + 5000 |
move $s2,$s0 | |
addi $s2,$s2,400 | # Marcador para indicar o final do array $gp + (100posições de 4bytes) |
Desta
forma temos os ponteiros necessários para trabalhar com o
primeiro array. O $s0 será o ponteiro e será
incrementado sempre em 4 posições para apontar
para a próxima word (próximo elemento). Vamos
armazenar nele um dado qualquer, como por exemplo um valor incrementado
sempre em 9 (9, 18, 27, 36...)
Detalhe importante: Para marcar pontos importantes no programa, utilizamos "labels" (rótulos). É através deles que executamos funções como jump e branch. Para definir um label, coloque um identificador seguido do sinal de dois pontos, ex: "repetir:" e escreva o código. Neste exercício faremos um loop para preencher os 100 elementos do array, por isso vamos precisar de um label para chamar a cada iteração. Quando o label é chamado (através de um bne por exemplo) a próxima instrução a ser executada é a da linha seguinte ao label.
li $t0,9 | # Carrega no reg. temporário $t0 um valor para ser armazenado no array |
dados: | |
sw $t0,0($s0) | # Armazena o valor na posição do array apontada por $s0 |
addi $s0,$s0,4 | # Aponta para a próxima posição no array (incrementa em 4 o ponteiro) |
addi $t0,$t0,9 | # Altera o valor a ser armazenado no array (incrementa em 9) |
bne $s0,$s2,dados | # Enquanto não chegar ao fim do array, repete o laço |
Vamos executar esta primeira parte do programa para testarmos o armazenamento dos valores do array. Salve o arquivo com o nome de "exercicio2a.s" e abra-o no SPIM. Execute o código (F5 e depois OK). Vamos verificar se ocorreu tudo bem. Na janela dos registradores o $s0 deverá estar em 10009518h que é a marca do final do array (o array inicia em 10009388h e o último elemento está em 10009514Ch). O registrador $t0 contém o valor 38Dh (909 em decimal), ou seja, o valor que seria armazenado na posição seguinte a última. Até aqui tudo Ok.
Agora verificaremos os valores em memória. Abra a janela Data Segment (Window, Data Segment). Ela deverá estar assim:
Aqui o SPIM apresenta os dados carregados em memória. Perceba que ele mostra somente as posições ocupadas. Os dados no array devem ser os seguintes: o valor 9 na primeira posição, o valor 18 na segunda e assim sucessivamente até o valor 900 na última posição. Podemos conferir os valores armazenados no nosso array: 9h, 12h, 1Bh... = 9, 18, 27... O último valor é 384h = 900. Tudo Ok até aqui!
Agora podemos continuar com o exercício. Vamos fazer a cópia dos dados para o array destino.
move $s0,$gp | |
addi $s0,$s0,5000 | # Definimos novamente o ponteiro para os dados do array fonte ($gp + 5000) |
move $s1,$gp | |
addi $s1,$s1,6000 | # Ponteiro para os dados do array destino ($gp + 6000) |
transfere: | |
lw $t0,0($s0) | # Armazena em t0 o conteúdo da posição apontada por $s0 (array fonte) |
sw $t0,0($s1) | # Armazena no array destino (apontado por $s1) o valor carregado |
addi $s0,$s0,4 | # Incrementa s0 em 4 (para chegar-se ao próximo elemento no array fonte) |
addi $s1,$s1,4 | # Incrementa s1 em 4 (para chegar-se ao próximo elemento no array destino) |
bne $s0,$s2,transfere | # Enquanto s0 não chegar em 400 (100 elementos), repete o laço |
Salve
novamente o arquivo ("exercicio2b.s")
e execute-o.
Agora
a janela de dados vai apresentar os dois arrays, sendo que o segundo
foi armazenado da posição 10009770h para
cima. Observe que esta posição é o $gp
(10008000h) + 6000.
Pronto! Os dados foram transferidos para o array destino.