Compilando Arrays com índice variável no MIPS

instrução MIPS LW e SW IF Simples no MIPS

Oi pessoal! Tudo bem? Espero que sim. Hoje retomo o assunto ARRAY, isto porque mostrei a vocês como compilar expressões matemáticas para MIPS quando o ARRAY, com índice específico, é um operando e quando ele armazena o resultado de uma operação. Porém faltou mostrar a compilação de quando o ARRAY tem um índice variável e não uma “posição” específica. Vamos lá então!

Compilando

Vou usar como exemplo a seguinte expressão matemática:

g = h + a[i];

Também farei a seguinte atribuição de registradores:

g = $s0            h = $s1            a = $s2            i = $s3

Note que agora o Array a possui um índice variável, que neste caso é o i, e não mais um índice específico, como, por exemplo, a[3] ou a[10]. Como então definir o i? Não sabemos quem é i, isso é verdade, não sabemos o seu valor, a sua posição, porém sabemos que i tem um endereço.

Também sabemos que o primeiro passo para a compilação desta expressão é ler a[i] carregando-o para um registrador temporário e, para isso, precisamos do seu endereço. Conforme explicado no artigo sobre a instrução SLT, o MIPS trabalha com endereçamento em bytes e, por isso, é necessário realizar um cálculo para o endereço, o qual sempre é múltiplo de 4. Assim sendo, no caso dos índices variáveis em Arrays, devemos multiplicar esses índices por 4. Mas, como fazer isto? Existem duas formas;

1 – Somar i até chegar em 4i

Nesta forma usamos a operação de soma, ADD, para chegar em 4*i, não fazemos a multiplicação direta. O registrador $s3 é a variável i, portanto, vamos começar somando esse registrador, armazenando o resultado em um registrador temporário:

ADD $t1, $s3, $s3                 # $t1 = $s3 + $s3        $t1 = i + i = 2*i

O registrador $t1 armazenou o valor 2*i, pois i + i é 2*i, correto?! Portanto, $t1 agora “vale” 2*i. Se fizermos $t1 + $t1 vamos obter 4*i, pois 2*i + 2*i = 4*i, confere? Usando o mesmo registrador temporário $t1 para armazenar o resultado, de forma a aproveitarmos melhor o uso dos registradores, veja como fica:

ADD $t1, $t1, $t1                  # $t1 = $t1 + $t1        $t1 = 2i + 2i = 4i

Essas duas linhas são referentes à soma de i até chegar em 4*i, isso garante que o endereço de i esteja correto, não importando o valor que ele contenha. Estamos falando aqui de um array, chamado a, o qual está atribuído ao registrador $s2, portanto, precisamos fazer o cálculo do endereço completo.

ADD $t1, $t1, $s2             # $t1 = ( $t1 + $s2 ) = ( 4*i + $s2) que é o mesmo que a[i]

Agora sim o cálculo do endereço de a[i] está completo e correto! Toda vez que encontrar um Array com índice variável, lembre-se de que, nesta forma de compilação, ele sempre vai resultar em três linhas de código no Assembly MIPS, as quais são três somas.

Da forma como mostrei aqui, o registrador $t1 acaba por ter o comportamento de um registrador acumulador (muitas vezes conhecido como ACC na Arquitetura Intel), que é aquele registrador que realiza operações e armazena resultados, consigo próprio. Agora que o endereço de a[i] já foi calculado, o restante da expressão pode ser compilada da forma que você já conhece, veja:

LW $t2,0($t1)                        # $t2 = a[i]

ADD $s0, $s2, $t2                 # g = h + a[i]

O código completo fica da seguinte forma:

ADD $t1, $s3, $s3      # 2*i

ADD $t1, $t1, $t1      # 4*i

ADD $t1, $t1, $s2      # a[i] = (4*i + $s2)

LW $t2, 0($t1)           # $t1 = a[i]

ADD $s0, $s1, $t2      # g = h + a[i]

Para essa instrução, g = h + a[i], e com esta forma de compilação, o código resultante em MIPS é de cinco linhas. Tente agora fazer a compilação para linguagem de máquina, representação e código de máquina.

2 – Usar a operação de deslocamento lógico à esquerda

Nesta forma de compilação não usamos a soma de forma a simular uma multiplicação. Ao invés disso, usamos a operação SLL, a qual gera o mesmo resultado que uma multiplicação por 2i. O deslocamento à esquerda de 2 bits multiplica por 22, ou seja, 4. A compilação ficará da seguinte forma:

SLL $t1, $s3, 2           # $t1 = 4*i

Na forma anterior precisamos de duas linhas para chegar no 4*i, já com a SLL uma única linha já nos fornece o resultado almejado. Ainda é preciso calcular o resto do endereço, somando $t1 com a base do Array a:

ADD $t1, $t1, $s2                # $t1 = ( $t1 + $s2 ) = ( 4*i + $s2) que é o mesmo que a[i]

O restante da compilação permanece o mesmo, veja:

LW $t2, 0($t1)           # $t1 = a[i]

ADD $s0, $s1, $t2      # g = h + a[i]

Usando SLL conseguimos diminuir em UM (1) a quantidade de linhas do código compilado em ASSEMBLY, o que não quer dizer que esse trecho de código será executado mais rapidamente. Nem sempre quantidade de linhas é sinônimo de execução rápida, as vezes com mais linhas a execução é mais rápida, as vezes não, e, as vezes em menos linhas a execução é mais rápida, as vezes não. Isso depende de uma série de outros fatores. Voltarei a falar sobre isso em artigos próximos, por hora, fica a reflexão! O código completo fica assim:

SLL $t1, $s3, 2           # 4*i

ADD $t1, $t1, $s2      # a[i] = (4*i + $s2)

LW $t2, 0($t1)           # $t1 = a[i]

ADD $s0, $s1, $t2      # g = h + a[i]

Tente fazer o restante da compilação: linguagem de máquina, representação e código de máquina.

Conclusão

Neste artigo você aprendeu a compilar uma instrução de alto nível com Array de índice variável, para um trecho de código em linguagem Assembly MIPS. Você pode também escolher o método para fazer isso. Não entendeu alguma coisa? Por favor, deixe aqui nos comentários que eu tentarei responder o mais breve possível. Obrigada leitor! Até o próximo artigo.

Saiba mais

SiFive lança o primeiro SoC RISC-V compatível com Linux

FE310G: Um microcontrolador open source – Interrupções no RISC-V

FE310G: Um microcontrolador open source – Estrutura básica do RISC-V

Outros artigos da série

<< Operandos Imediatos e Constantes no MIPSTestando as instruções MIPS no MARS >>
Website | Veja + conteúdo

Atuo como Professora de Informática e Computação desde 2001, atendendo de forma especial a Terceira Idade e Concurseiros. Desde 2009 venho atuando como Docente no Ensino Superior em diversos cursos de Graduação e Pós Graduação Lato Sensu, tanto presenciais, quanto semipresenciais e à distância. Ministrei várias disciplinas onde ensino os estudantes a desenvolverem plataformas e sistemas computacionais. Orientei vários trabalhos acadêmicos, desenvolvi inúmeros materiais, trabalhei com pesquisa, ensino, extensão e inovação, ministrei palestras em vários eventos. Mais recentemente venho ofertando serviços na área de tecnologia como desenvolvimento de sistemas, treinamentos, consultoria, mentoria, etc. Comecei meu Doutorado na área de Machine Learning (Multi-label Classification) na UFSCar em 02/2019 e devo terminar em 01/2023. Também estudo canto, jogo vôlei, sou geek, nerd, otaku e gamer!

Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.

Receba os melhores conteúdos sobre sistemas eletrônicos embarcados, dicas, tutoriais e promoções.

Comentários:
Notificações
Notificar
guest
0 Comentários
Inline Feedbacks
View all comments
Talvez você goste:

Séries



Outros da Série

Menu