Compilando Potência no MIPS

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

Neste artigo vamos entender como calcular x^y (x elevado a y) no MIPS usando o MARS simulator. Pra fazer isso precisaremos usar recursão. Caso ainda não saiba sobre o assunto, recomendo ler os artigos a seguir antes de prosseguir aqui:

Recursividade

Compilando Procedimentos Recursivos e Aninhados no MIPS

Função Potência

Quando fazemos um número x elevado a um número y, basicamente estamos dizendo que o número x deve ser multiplicado por ele mesmo uma quantidade de vezes em y. Exemplo: 2^5 = 2 * 2 * 2 * 2 * 2 = 32. Por isso a função em C é recursiva. O trecho de código a seguir apresenta a função potência em linguagem C. Esta será a função que vamos implementar no MIPS.

Essa função solicita 2 inteiros e depois verifica se y é diferente de zero. Se este não é o caso, então executa o que está no ELSE, que é apenas retornar o valor 1 pois qualquer número elevado a zero é 1. Se y é de fato diferente de zero, então podemos fazer a operação. A Figura a seguir decupa como ocorre a execução:

Potência no MIPS

Como podemos ver, é possível abstrair o cálculo de forma que resulta na equação que está no return da função em C. O resultado da primeira multiplicação pode ser usado para calcular o valor de x^y até chegar no y. Por exemplo, se você solicitar o valor de 2^10, a função será chamada 10 vezes recursivamente de forma que: o resultado de 2^1 é armazenado e usado para calcular 2^2; o resultado de 2^2 é armazenado e usado para calcular 2^3 e assim por diante até chegar no 2^10. Deu pra compreender pessoal? Caso vocês não tenham entendido o processo, por favor, deixem ali nos comentários o que não fico claro que responderei.

Implementação do calculo de Potência no MIPS

Agora que já vimos como funciona a função em C, vamos codificá-la em MIPS. Aqui vamos passar os valores de x e y diretamente no código e também vamos usar funções, assim como strings para apresentar o resultado no console. Essas informações vão no segmento de dados identificado como .data no código.

Usamos o .word para dizer que o número 2, o número 10 e a variável Resultado tem o tamanho de uma palavra, que é 32 bits. A mensagem que será impressa no console deve ser indicada com a diretiva .asciiz. Aqui podemos usar \n e \t normalmente para pular linha e dar espaço entre textos.

Agora que finalizamos o segmento de dados, vamos começar o segmento de texto, que é o espaço reservado para o código MIPS propriamente dito. Como vamos usar funções, então vamos usar a diretiva .globl pra indicar que as funções ficarão visíveis globalmente. Usaremos o rótulo main para indicar o programa principal e o rótulo potencia para indicar a função potencia.

Devo reforçar que aqui as funções no MARS devem ser implementadas depois do programa MAIN. Vamos começar implementando a função principal ok. Primeiro vamos carregar os valores de x e y:

Usamos a instrução LW pra carregar 2 e 10 nos registradores de argumentos da função, já que eles são os dois parâmetros x e y. Portanto, x será carregado em $a0 que é o primeiro argumento da função, e y será carregado em $a1 que é o segundo argumento da função. Agora que já temos os argumentos da função, podemos chamá-la:

Depois que a função é chamada, executada e finalizada, é possível obter e imprimir o resultado no console usando uma chamada do sistema. Para obter o resultado usamos a instrução sw que salva o resultado retornado da função que está em $v0 na variável Resultado. Somente assim é que conseguiremos imprimir depois.

Usamos o inteiro 4 para indicar que queremos imprimir no console uma string, o qual é passado para $v0 que é o registrador que será usado na chamada do sistema. A instrução li (load immediate) é usada pois estamos carregando um número diretamente (imediatamente) no registrador. Em seguida usamos a instrução la para carregar o endereço da string que está armazenada em MENSAGEM no registrador $a0. Por último, chamamos syscall que de fato imprimirá a mensagem na tela.

Precisamos mandar imprimir o resultado também, para isso usamos outra chamada de sistema. O código 1 é passado como valor para impressão de números inteiros no registrador $v0 e a variável Resultado é carregada no registrador $a0. Agora com os dois parâmetros da chamada do sistema carregados podemos de falto chamar o sistema para imprimir no console:

Agora tudo o que precisamos fazer é finalizar corretamente o programa:

A função completa fica da seguinte forma:

A função principal está codificada. Vamos agora codificar a função potencia. Como é uma função recursiva precisaremos usar o recurso de LOOP para que a função funcione corretamente e por isto damos o nome de potencia ao rotulo da função e também ao rótulo do LOOP. Começamos inicializando y e o contador do loop, assim, o registrador $t0 é o contador e $v0 é nosso y.

Agora começamos a codificar o loop. Primeiro precisamos verificar se y é igual é zero. Se este for o caso, então o LOOP não ocorre, então devemos sair do LOOP e continuar com a execução do resto do programa, ou apenas sair do programa. Lembram que quando um número x é elevado a zero o resultado é 1. Esta é a parte que decodificamos agora.

A instrução BEQ é responsável por fazer esta comparação. A lógica nos diz que se o segundo argumento da função $a1, que é nosso y, for igual a zero então, vá para o ELSE. Note que no meu código não estou fazendo uma comparação diretamente com zero, mas sim com dez. O que estou fazendo na verdade é comparar o valor do registrador $a1 com o valor do registrador $t0 e verificando se naquele momento $a1==10. Quando $a1==10 o LOOP termina. O que vai acontecer no LOOP nesta comparação é o seguinte:

Iteração$a1$t0Desvia?
1100não
2101não
3102não
4103não
5104não
6105não
7106não
8107não
9108não
10109não
111010sim

O LOOP começa com $a1 valendo 10 e $t0 valendo zero. Cada vez que entra no LOOP o contador $t0 é incrementado em 1 mas o valor de $a1 nunca muda. Dessa forma, o LOOP executará corretamente a quantidade de vezes que são necessárias para realizar a potência. Note que x é o argumento $a0 por isso o multiplicamos por $v0 que é o parâmetro de retorno da função. Bom, agora temos que codificar a multiplicação de x por ele mesmo e também o incremento do contador:

O corpo do LOOP está pronto só falta agora o retorno para o LOOP enquanto $a1 != $t0

j potencia_loop volta para o inicio do loop. O código completo da função fica como a seguir:

O código completo do problema ficará da seguinte forma:

Finalizando

Pessoal, espero que vocês tenham entendido. Caso tenham ficado dúvidas, por favor, deixem nos comentários. Sugiro que vocês tentem implementar outras operações matemáticas recursivas para treinar. Agradeço muito por terem lido este artigo até o final. Lembrem de recomendá-lo para seus amigos tá ok?!!! Até o próximo

Outros artigos da série

<< MIPS: Resolução de Exercícios Parte 2Criando e Manipulando Matrizes no MIPS >>
Sem licença Creative Commons

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

Home » Hardware » Compilando Potência no MIPS
Comentários:
Notificações
Notificar
guest
0 Comentários
Inline Feedbacks
View all comments
Talvez você goste:
Nenhum resultado encontrado.

Séries

[vc_widget_sidebar sidebar_id=”us_widget_area_series”]
Menu