- Arquitetura de Conjunto de Instruções MIPS
- Primeira Instrução MIPS
- Compilação de Expressões no MIPS
- Convertendo uma instrução com Array no MIPS
- Armazenando um valor em Array no MIPS
- Instruções LW e SW com Array no MIPS
- Instrução IF Simples no MIPS
- Instrução IF Composto no MIPS
- Instrução SLT no MIPS
- Operações Lógicas no MIPS
- Operação Lógica AND no MIPS
- Operação Lógica OR no MIPS
- Operação Lógica NOT no MIPS
- Endereços de Memória no MIPS
- Operandos Imediatos e Constantes no MIPS
- Compilando Arrays com índice variável no MIPS
- Testando as instruções MIPS no MARS
- Executando um Array no MARS para MIPS
- Sinal e Overflow no MIPS
- Compilando instruções com ou sem Sinal, Overflow e Imediato no MIPS
- Compilando While no MIPS
- Compilando Switch/Case no MIPS
- Compilando Funções e Procedimentos no MIPS
- Compilando Procedimentos Recursivos e Aninhados no MIPS
- Detalhamento da Compilação de Procedimentos no MIPS
- MIPS: Instruções de Multiplicação
- MIPS: Instruções de Divisão
- MIPS: Subtração e outras instruções
- Compilando o comando FOR no MIPS
- Ponto Flutuante no MIPS
- Convertendo Código de Máquina em Assembly MIPS – Parte 1
- MIPS: Resolução dos exercícios – Parte 1
- MIPS: Resolução de Exercícios Parte 2
- Compilando Potência no MIPS
- Criando e Manipulando Matrizes no MIPS
Oi pessoal. Hoje nós vamos começar com as instruções MIPS e, conforme formos “caminhando”, vou apresentando os detalhes do MIPS.
Todo software é traduzido para a linguagem binária (0 e 1) pra poder ser executado pelo processador. Quando você está com o computador ligado, usando quaisquer programas, todos eles estão sendo traduzidos e executados pelo seu processador. Se você desenvolve software, sabe que as instruções do seu programa serão convertidas para 0 e 1. Enfim, a linguagem da máquina é 0 e 1, mas a nossa linguagem não.
Eu não sei falar Chinês, mas se eu precisar conversar com um Chinês, solicitarei a ajuda de alguém que saiba essa língua, provavelmente um tradutor. Assim, com um tradutor, o Chinês e eu poderemos conversar igualmente. É a mesma coisa entre os programas e o hardware.
Considere a seguinte instrução em linguagem C:
a = b + c;
Essa instrução, para ser executada no processador, deve ser convertida para MIPS e depois para 0 e 1. Para poder manipular as variáveis é necessário utilizar os registradores do MIPS. Acredito que todos já saibam que a CPU é composta por registradores, que é a memória mais rápida e mais cara do projeto de um microprocessador, justamente porque está na CPU, para ajudar a executar as instruções.
Para as conversões usamos os registradores de uso geral do MIPS. Normalmente, nas nossas conversões, as variáveis que armazenam valores usam os registradores de nome t e as variáveis que contêm os operandos usam os registradores de nome s. A Tabela 1 apresenta os 32 registradores do MIPS 32 bits.
Tabela 1: Os 32 Registradores de uso geral do MIPS 32 bits.
Nome do Registrador | Número | Binário | Uso |
$zero | 0 | 000 000 | constante zero |
$at | 1 | 000 001 | reservado para o montador |
$v0 | 2 | 000 010 | avaliação de expressão e resultados de uma função |
$v1 | 3 | 000 011 | avaliação de expressão e resultados de uma função |
$a0 | 4 | 000 100 | argumento 1 (passam argumentos para as rotinas) |
$a1 | 5 | 000 101 | argumento 2 |
$a2 | 6 | 000 110 | argumento 3 |
$a3 | 7 | 000 111 | argumento 4 |
$t0 | 8 | 001 000 | temporário (valores que não precisam ser preservados entre chamadas) |
$t1 | 9 | 001 001 | temporário |
$t2 | 10 | 001 010 | temporário |
$t3 | 11 | 001 011 | temporário |
$t4 | 12 | 001 100 | temporário |
$t5 | 13 | 001 101 | temporário |
$t6 | 14 | 001 110 | temporário |
$t7 | 15 | 001 111 | temporário |
$s0 | 16 | 010 000 | temporário salvo (valores de longa duração e devem ser preservados entre chamadas) |
$s1 | 17 | 010 001 | temporário salvo |
$s2 | 18 | 010 010 | temporário salvo |
$s3 | 19 | 010 011 | temporário salvo |
$s4 | 20 | 010 100 | temporário salvo |
$s5 | 21 | 010 101 | temporário salvo |
$s6 | 22 | 010 110 | temporário salvo |
$s7 | 23 | 010 111 | temporário salvo |
$t8 | 24 | 011 000 | temporário |
$t9 | 25 | 011 001 | temporário |
$k0 | 26 | 011 010 | reservado para o Kernel do sistema operacional |
$k1 | 27 | 011 011 | reservado para o Kernel do sistema operacional |
$gp | 28 | 011 100 | ponteiro para área global |
$sp | 29 | 011 101 | stack pointer (aponta para o último local da pilha) |
$fp | 30 | 011 110 | frame pointer (aponta para a primeira palavra do frame de pilha do procedimento) |
$ra | 31 | 011 111 | endereço de retorno de uma chamada de procedimento |
De acordo com a tabela, usaremos então os registradores que vão de $t0 à $t7 e de $s0 à $s7. A instrução a = b + c ficará da seguinte forma:
ADD $t0, $s0, $s1
ADD é o mnemônico para ADIÇÃO, $s0 é o valor que está armazenado em b, $s1 o valor da variável c e $t0 é a variável a. Essa é a instrução Assembly MIPS correspondente à instrução em linguagem C, também chamada de Linguagem de Montagem. Mas isso ainda não é suficiente para que a instrução seja executada no microprocessador. Os nomes dos registradores usados aqui foram escolhidos arbitrariamente, mas durante a execução real são usados os registradores que estiverem livres naquele instante.
O próximo agora é converter a instrução de Linguagem de Montagem para Linguagem de Máquina. Cada registrador tem um número, conforme apresenta a Tabela 1. A Linguagem de Máquina corresponde a trocar o NOME DO REGISTRADOR pelo seu NÚMERO. A instrução ficará da seguinte forma:
ADD $8, $16, $17
Simples né? Agora, o próximo passo é fazer a REPRESENTAÇÃO da instrução. No MIPS existem três FORMATOS de instruções, veremos um agora, que é o formato do tipo R (registrador).
Tabela 2: Formato de Instrução do Tipo R
op | rs | rt | rd | shamt | funct |
6 bits | 5 bits | 5 bits | 5 bits | 5 bits | 6 bits |
opcode ou código da operação | registrador do primeiro operando fonte | registrador do segundo operando fonte | registrador do operando destino | deslocamento |
função de operação ou código de função |
Todas as instruções no MIPS 32 têm exatamente 32 bits e cada formato de instrução tem campos diferentes. O formato R é dividido em seis campos, sendo os campos OP e FUNCT com 6 bits e o restante com 5 bits, totalizando 32 bits.
O primeiro campo, OP, é destinado para identificação do código de operação que será realizada. O último campo seleciona uma operação secundária, por exemplo, a operação principal é a aritmética, mas a secundária é uma soma. Nem todas as operações têm dois códigos (op-funct) e nesse caso o campo FUNCT é setado com o valor zero.
Os campos RS e RT são destinados aos operandos fontes, em ordem, da esquerda para a direita, conforme aparecem na operação. Já o campo RD é destinado para o armazenamento do resultado da operação, portanto, operando destino. Shamt é um campo usado para setar uma quantidade de deslocamento mas, por hora, não o usaremos, por isso será setado com o valor zero.
Precisamos também conhecer as operações e seus valores decimais correspondentes. A Tabela 3 apresenta os valores binários e decimais para cada instrução que utilizaremos nesta série. Por hora, guardem a Tabela e não se preocupem com as instruções, nós as aprenderemos ao longo da série.
Tabela 3: Opcodes
OPCODE | DECIMAL | BINÁRIO |
ADD | 32 | 100 000 |
SUB | 34 | 100 010 |
OR | 36 | 100 100 |
AND | 37 | 100 101 |
SLT | 42 | 101 010 |
BNE | 4 | 000 100 |
BEQ | 5 | 000 101 |
J | 2 | 000 010 |
JR | 8 | 001 000 |
LW | 35 | 100 011 |
SW | 43 | 101 011 |
Consultando a Tabela 3, a instrução ficará da seguinte forma:
op | rs | rt | rd | shamt | funct |
0 | $16 | $17 | $8 | 0 | 32 |
Instruções de formato tipo R sempre terão o opcode igual a zero e funct será correspondente à instrução específica. A instrução está representada no seu formato específico, agora fica bem mais fácil pra chegar no código de máquina, conforme abaixo:
op | rs | rt | rd | shamt | funct |
000000 | 10000 | 10001 | 01000 | 00000 | 100000 |
O código binário 00000010000100010100000000100000 é a instrução a = b + c em MIPS 32 bits. Diante de tudo o que vimos até aqui, podemos fazer um algoritmo passo a passo para realizar a conversão:
1. Converter a instrução de alto nível para Linguagem de Montagem;
2. Converter a instrução na Linguagem de Montagem para Linguagem de Máquina;
3. Fazer a representação correspondente da Linguagem de Máquina;
4. Converter a representação da Linguagem de Máquina para Código de Máquina.
Tranquilo não é? Bom, no próximo artigo veremos outros detalhes, mostrarei outra instrução e como ela será convertida. Espero que este artigo tenha sido útil pra vocês. Caso tenham dúvidas, por favor, deixem nos comentários. Muito Obrigada!
A tabela 3:opcode têm os tens AND E O OR estão trocados
AND = 36
OR = 37
obrigada por avisar, tá correto agora será? eu já fiz a correção, me avise qq coisa
Qual é o opcode da divisão em binário?
da uma olhaada aqui ta bom: https://opencores.org/projects/plasma/opcodes
Parabéns pelos artigos que elaborou, nesse momento de quarentena estão servindo muito para expandir os conhecimentos…estou perdendo o preconceito com a área de eletrônica e da ciência da computação e estou me apaixonando, sem nenhum esforço rs’. Espero que continue nos enriquecendo com seus conhecimentos, forte abraço ^ ^.
Oi Igor, obrigada pelo seu comentário e desculpe a demora para responder. Ando bem ocupada com o doutorado. Fico muito feliz em saber que estou te ajudando de alguma forma. Boa sorte na sua caminhada.
Sera que alguem poderia me ajudar a resolver um exercicio?
Oi Rayn, o que você precisa?
Parabéns Elaine pela qualidade do material que disponibiliza. Sucesso! Kleber.
Oi Kleber, muito obrigada =)
@elainececliagatto:disqus, muito bom o artigo, parabéns! Já estou aguardando o próximo artigo! Só fiquei com uma dúvida básica. Por exemplo, quando quero somar 4 + 2, tenho que converter esse dois valores em decimas para binário e colocar os valores correspondentes nos registradores rs e rt, e o resultado que é 6 ficará armazenado em binário em rd. Está correto esse meu entendimento?
Roniere, na verdade pra trabalhar com valores diretamente como você está sugerindo temos de usar outro tipo de instrução, que chamamos de instruções IMEDIATAS! Ao invés de usar ADD usamos ADDI e elas funcionam relativamente iguais, mas o MODO DE ENDEREÇAMENTO é outro. Neste artigo estou mostrando como somar QUAISQUER valores que estejam armazenados em memória, independente do seu valor real, são instruções que utilizam Registradores temporários para manipular esses valores. Sem sombra de dúvidas que em algum momento os valores armazenados nas variáveis deverão ser codificados para 0 ou 1, mas isso ficará mais claro quando eu mostrar pra… Leia mais »
Gostei muito do artigo, Elaine. É difícil encontrar materiais sobre MIPS didáticos assim em língua portuguesa.
Parabéns pela didática. Aguardando o próximo! =]
Oi Renato!!! Muito Obrigada =) Fico feliz que você tenha gostado. Semana que vem tem mais, aguarde.