Vetores: indexação por posição
Um vetor é um array: uma sequência de números armazenados um ao lado do outro na memória. Na lição anterior, você somou um avançando um ponteiro em 4 bytes para cada elemento. Esse mesmo método funciona aqui. Há outra maneira comum de alcançar um elemento: por índice. Um índice é a posição de um elemento contada a partir do início, em que o primeiro elemento tem índice 0, o segundo tem índice 1, e assim por diante.
Somar um vetor avançando um ponteiro
.dataa: .word 5, 10, 15, 20 # quatro elementos.textla t0, a # t0 = endereço de ali t1, 4 # t1 = número de elementos restantesli t2, 0 # t2 = soma correnteloop:beq t1, zero, donelw t3, 0(t0) # carrega o elemento atualadd t2, t2, t3 # soma ao totaladdi t0, t0, 4 # avança para a próxima palavra (4 bytes)addi t1, t1, -1 # um a menosj loopdone:mv a0, t2 # imprime o total: 5+10+15+20 = 50li a7, 1ecallli a7, 10ecall
O loop funciona da seguinte forma. t0 contém o endereço de a, e t1 contém o número de elementos restantes, começando em 4. A cada passagem, encerra o loop quando a contagem chega a zero. carrega o elemento no endereço em t0. adiciona esse valor ao total acumulado. avança o ponteiro para a próxima palavra. diminui a contagem. Após quatro passagens (5 + 10 + 15 + 20), done imprime 50. Esse é o mesmo padrão usado na lição de memória, agora aplicado a um vetor.
Do índice ao endereço
A indexação calcula um endereço a partir de um ponteiro base e uma posição: address = base + index * 4. O 4 é o tamanho de uma palavra em bytes. Um compilador gera esse mesmo cálculo para a[i] em uma linguagem como C. O índice em si nunca acessa a memória. Apenas o endereço calculado a partir dele o faz.
slli t5, t3, 2 # t5 = índice * 4 (tamanho de uma palavra)add t6, t0, t5 # t6 = endereço de element[index]lw t6, 0(t6) # t6 = element[index]
desloca o índice em t3 2 bits para a esquerda, o que o multiplica por 4 (dois dobros: 2 x 2), o tamanho de uma palavra. Somar o resultado ao ponteiro base dá o endereço de element[index]. Esse deslocamento é o mesmo método de potência de dois da lição de aritmética, e é a maneira padrão de escalar um índice pelo tamanho de uma palavra.
a[0]: índice 0, deslocamento 0.
i como uma posição, e o endereço que essa posição produz depois que o escala por 4 e o soma à base. Os números hexadecimais são os endereços reais que a ocupa quando o simulador executa este programa. O objetivo é prever o próximo endereço antes que ele apareça. Isso permite que você leia dentro de um loop incremental, ou a[i] em uma linguagem do tipo C, e visualize o endereço de memória que ele acessa em vez de tratar a notação como uma caixa preta.Somando um vetor por índice
.dataa: .word 5, 10, 15, 20 # quatro elementos.textla t0, a # t0 = endereço base de ali t1, 4 # t1 = número de elementosli t2, 0 # t2 = índice, começa em 0li t3, 0 # t3 = total acumuladoloop:beq t2, t1, doneslli t4, t2, 2 # t4 = índice * 4 (deslocamento em bytes)add t5, t0, t4 # t5 = endereço de a[index]lw t5, 0(t5) # t5 = a[index]add t3, t3, t5 # total += a[index]addi t2, t2, 1 # avança para o próximo índicej loopdone:mv a0, t3 # imprime o total: 5+10+15+20 = 50li a7, 1ecallli a7, 10ecall
O loop funciona da seguinte forma. t2 é o índice, começando em 0. A cada passagem, encerra o loop quando o índice chega a 4, a contagem de elementos contida em t1. converte o índice em um deslocamento em bytes. soma esse deslocamento ao endereço base em t0 para produzir o endereço de a[index]. carrega o valor armazenado ali. Esse valor é somado ao total acumulado em t3, e avança para o próximo índice. Após quatro passagens (5 + 10 + 15 + 20), done imprime 50.
Somando dois vetores, elemento por elemento
.dataa: .word 3, 6, 9, 12 # primeiro vetorb: .word 1, 2, 3, 4 # segundo vetorc: .space 16 # espaço para 4 palavras de resultado.textla t0, a # endereço base de ala t1, b # endereço base de bla t2, c # endereço base de cli t3, 0 # índice, começa em 0li t4, 4 # número de elementosli s0, 0 # total correnteloop:beq t3, t4, doneslli t5, t3, 2 # deslocamento em bytes = índice * 4add t6, t0, t5 # endereço de a[index]lw t6, 0(t6) # valor de a[index]add a0, t1, t5 # endereço de b[index]lw a0, 0(a0) # valor de b[index]add t6, t6, a0 # a[index] + b[index]add a0, t2, t5 # endereço de c[index]sw t6, 0(a0) # c[index] = a[index] + b[index]add s0, s0, t6 # total += c[index]addi t3, t3, 1 # avança para o próximo índicej loopdone:mv a0, s0 # imprime o total: 4+8+12+16 = 40li a7, 1ecallli a7, 10ecall
O loop funciona da seguinte forma. converte o índice t3 em um deslocamento em bytes. Somá-lo a cada ponteiro base (t0, t1, t2) dá os endereços de a[i], b[i] e c[i]. A cada passagem, ambos os elementos são carregados, somados, armazenados em c, e adicionados ao total acumulado em s0. avança para o próximo índice, e o loop se repete até que todos os quatro elementos sejam processados.
