- 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
Oi pessoal. No último artigo eu mostrei a vocês como começar a trabalhar com ponto flutuante. Desde então, algumas pessoas me procuraram para tirar dúvidas sobre o MIPS, e então tive algumas ideias para dar continuidade na série. Hoje, portanto, mostrarei a vocês como converter um código de máquina em Assembly Mips, que é um dos tópicos que geram bastante dúvidas. O artigo será na forma de resolução de um exercício, para ficar mais fácil o entendimento tá ok! Então, primeiro darei o enunciado e, a partir dele, farei a resolução passo a passo. Bora lá?
Enunciado
Considere que estamos trabalhando com uma máquina litte-endian. Considere também a memória de dados apresentada na Tabela I, a memória de instruções apresentada na Tabela II, ambas em hexadecimal, e o banco de registradores apresentado na Tabela III. Faça:
- Converta a memória de instruções em código Assembly MIPS;
- Quais tipos de instruções estão presentes?
- Quantas instruções de cada tipo estão presentes?
- Quantos bytes estão contidos na memória de dados?
- Quantos bytes ocupa o código Assembly?
- Execute o código assembly mips passo a passo, isto é, a partir dos valores iniciais dados na Tabela II, execute todas as instruções, anotando os valores resultantes. Anote mudanças nos valores de endereços de memória, de dados e do banco de registradores.
Tabela 1: Memória de Dados
Endereço de Memória |
Dados | |||
Byte 3 |
Byte 2 |
Byte 1 |
Byte 0 | |
0x 1000 0018 |
12 |
34 |
56 |
A1 |
0x 1000 0014 |
10 |
05 |
06 |
07 |
0x 1000 0010 |
BB |
AA |
CC |
11 |
0x 1000 000C |
00 |
00 |
00 |
06 |
0x 1000 0008 |
A0 |
0B |
1C |
D1 |
0x 1000 0004 |
04 |
FF |
F2 |
F0 |
0x 1000 0000 |
FF |
AA |
D1 |
20 |
Tabela 2: Memória de Instruções
Endereço de Memória |
Instruções | |||
Byte 3 |
Byte 2 |
Byte 1 |
Byte 0 | |
0x 0040 0020 |
AE |
13 |
00 |
10 |
0x 0040 001C |
A2 |
12 |
00 |
07 |
0x 0040 0018 |
AE |
11 |
00 |
00 |
0x 0040 0014 |
22 |
32 |
FF |
FC |
0x 0040 0010 |
02 |
2A |
90 |
22 |
0x 0040 000C |
01 |
09 |
88 |
20 |
0x 0040 0008 |
82 |
0A |
00 |
15 |
0x 0040 0004 |
8E |
09 |
00 |
0C |
0x 0040 0000 |
8E |
08 |
00 |
04 |
Tabela 3: Banco de Registradores
N.º do Registrador |
Nome do Registrador |
Conteúdo | |||
Byte 3 |
Byte 2 |
Byte 1 |
Byte 0 | ||
0 |
$zero |
|
|
|
|
1 |
$at |
|
|
|
|
2 |
$v0 |
|
|
|
|
3 |
$v1 |
|
|
|
|
4 |
$a0 |
|
|
|
|
5 |
$a1 |
|
|
|
|
6 |
$a2 |
|
|
|
|
7 |
$a3 |
|
|
|
|
8 |
$t0 |
09 |
08 |
03 |
02 |
9 |
$t1 |
11 |
FF |
FF |
F1 |
10 |
$t2 |
00 |
00 |
00 |
0F |
11 |
$t3 |
01 |
21 |
51 |
A1 |
12 |
$t4 |
00 |
01 |
10 |
17 |
13 |
$t5 |
|
|
|
|
14 |
$t6 |
|
|
|
|
15 |
$t7 |
|
|
|
|
16 |
$s0 |
10 |
00 |
00 |
00 |
17 |
$s1 |
11 |
22 |
30 |
03 |
18 |
$s2 |
A1 |
FF |
10 |
C2 |
19 |
$s3 |
10 |
09 |
34 |
55 |
20 |
$s4 |
22 |
00 |
11 |
01 |
21 |
$s5 |
|
|
|
|
22 |
$s6 |
|
|
|
|
23 |
$s7 |
|
|
|
|
24 |
$t8 |
|
|
|
|
25 |
$t9 |
|
|
|
|
26 |
$k0 |
|
|
|
|
27 |
$k1 |
|
|
|
|
28 |
$gp |
|
|
|
|
29 |
$fp |
|
|
|
|
30 |
$sp |
|
|
|
|
31 |
$ra |
|
|
|
|
Resolução
– Questão 1: Converta a memória de instruções em código Assembly MIPS
Passo 1: Conversão Hexadecimal para Decimal
- Converter os valores hexadecimais para binário, começando a partir do endereço 0x 0040 0000, isto é, a conversão começa de baixo para cima.
Passo 2: OPCODE
- Descobrir o OPCODE de cada instrução a partir dos bits 31 a 26. Ao separar esses seis bits, consultar a referência de arquitetura do MIPS 32 bits no link 1. Um resumo você também encontra aqui no embarcados no link 2. Para facilitar, farei a separação dos bits conforme o formato de instrução R. Quando convertemos os bits em número decimal, temos o opcode correspondente da instrução. Com ele podemos consultar a referência de arquitetura e assim verificar qual é a instrução correspondente.
- https://www.mips.com/products/architectures/mips32-2/
- https://www.embarcados.com.br/primeira-instrucao-mips/
Passo 3: FUNCT
- Observe que as instruções aritméticas têm opcode zero, então precisamos descobrir, qual é de fato, a operação aritmética que será executada ali. O campo FUNCT é o responsável por nos dar essa informação, e ele corresponde aos bits de 5 a 0, assim, vamos olhar para esses bits, verificar qual é o número decimal e consultar a instrução correspondente.
Passo 4: Formato de Instrução
- Agora que já sabemos os OPCODES e os FUNCT, podemos separar os restantes dos bits, conforme o tipo de instrução identificada: tipo R, tipo I ou tipo J. Depois disso, vamos converter número binário para decimal.
Passo 5: Convertendo para decimal
- Depois de dividirmos os formatos, agora convertemos o número binário para decimal.
Passo 6: construindo as instruções
- Neste passo, vamos construir corretamente as instruções, de acordo com o passo anterior. Devemos lembrar que precisamos trocar as posições dos registradores. Até o momento, usei o formato para poder identificar os valores hexadecimais, binários e decimais corretamente, mas não significa que eles estejam no campo correto.
- Isso nos dá as seguintes instruções:
- Pronto, terminamos a conversão do código de máquina para assembly. O código assembly MIPS final é:
– Questão 2: Quais tipos de instruções estão presentes?
- R.: Instruções do tipo R e tipo I
– Questão 3: Quantas instruções de cada tipo estão presentes?
- R.: No total são sete instruções do tipo I e duas instruções do tipo R. São três instruções do tipo load, três instruções do tipo store, duas instruções aritméticas e uma instrução aritmética com imediato.
– Questão 4: Quantos bytes estão contidos na memória de dados?
- R.: Para encontramos este valor, temos de pensar da seguinte maneira. Cada linha da memória de dados possui 32 bits, pois como bem sabemos, no MIPS 32 bits, sempre manipulamos 32 bits. A memória de dados tem 7 linhas, então, azemos 32 vezes 7, o que nos dá 224 bits. No entanto, a questão pede a quantidade de bytes. Bem, 1 byte é o mesmo que 8 bits, então, dividimos 224 bits por 8 e temos como resultado 28 bytes. De maneira forma, a conta seria o seguinte:
TotalBytes = (totalLinhas x 32) / 8
– Questão 5: Quantos bytes ocupa o código Assembly?
- R.: Aqui usamos o mesmo racicínio da questão anterior. Assim temos que a memória de instruções possui 9 linhas, portanto: 9 * 32 = 288 bits, e 288/8 = 36 bytes
Conclusão deste artigo
Até aqui mostrei como se converte um código de máquina em código Asssembly. Mostratei a resolução da questão número 6 no próximo artigo, para que este não fique muito longo. Tudo bem galera? Tendo dúvidas, por favor, deixem aqui nos comentários.