Você está na página 1de 64

Introdução a programação em

assembly da Arquitetura MIPS


Prof. Dr. Marcos Laia
Aula 1: Introdução ao RISC e
MIPS
1. O que é RISC (Reduced Instruction Set
Computer)?
• RISC, que significa "Computador com Conjunto Reduzido de
Instruções", refere-se a uma arquitetura de CPU que utiliza um
conjunto de instruções simples e de tamanho fixo.
• A ideia por trás do RISC é que, ao simplificar as instruções, a CPU
pode executar operações mais rapidamente, permitindo um maior
desempenho.
CISC x RISC
CISC
Complex Instruction Set Computer
• Praticamente todos os processadores têm base CISC:
– Intel 8080, Motorola 6800, Z-80
– Intel 80486, Motorola MC 68040
– Minicomputadores: VAX-11, AS-400
– Mainframes, computadores de grande porte
Z80 – 8 bits
Arquitetura z80
msx
Zx spectrum
Motorola 68k
CISC
Complex Instruction Set Computer
• À medida que novas instruções são acrescidas:
– Decodificador de instruções fica mais complexo e mais lento;
– Microcódigo fica maior gerando lentidão;
– Processador fica maior e mais difícil de ser construído.
RISC
Reduced Instruction Set Computer
• Contrapõe-se a arquitetura CISC predominante;
– Identificação de um tipo de arquitetura de CPU (e de todo um
sistema de computação);
• Exemplo: Sun
– Desenvolveu as estações de trabalho SPARC;
– Foi a primeira empresa a abrir um mercado de rápido crescimento.
RISC
Reduced Instruction Set Computer
• Computador com um conjunto reduzido de instruções:
• Menor quantidade de instruções que as máquinas CISC de mesma
capacidade.
• A SPARC da Sun possui cerca de 50 instruções, enquanto os VAX-
11/780 apresentavam até 303 instruções.
Sun Sparc
Silicon Graphics
2. Histórico
• A ideia de RISC começou na década de 1970, principalmente em
universidades e centros de pesquisa.
• John Cocke, da IBM, é frequentemente creditado como o pioneiro por
trás do conceito RISC, com o projeto IBM 801.
• Durante os anos 80 e 90, o RISC tornou-se uma tendência dominante
na indústria de computadores, com muitas empresas desenvolvendo
suas próprias versões de CPUs RISC.
RISC
Reduced Instruction Set Computer
• Instruções com execução otimizada
– Resultado melhor com melhor desempenho;
– Conduz a programas mais longos.
• Não possui decodificador de instruções;
• Não possui microcódigo.
• Boa parte da complexidade da CPU é transferida para o compilador
– Gera programas otimizados.
Vantagens
• Desempenho mais rápido: Devido à simplicidade das instruções, as
operações podem ser executadas mais rapidamente.
• Eficiência de energia: Menos complexidade significa menos consumo
de energia.
• Menor custo de fabricação: Menos complexidade também pode levar
a um custo de fabricação reduzido.
• Flexibilidade: Os designers podem adicionar mais recursos, como
unidades de processamento paralelo ou mais caches, devido ao
espaço economizado.
Introdução ao MIPS (Microprocessor without
Interlocked Pipeline Stages)
• MIPS é uma arquitetura de microprocessador RISC que foi
desenvolvida na década de 1980 pela MIPS Computer Systems.
• A arquitetura MIPS foi uma das primeiras arquiteturas comerciais
RISC e teve um impacto significativo na indústria de
microprocessadores.
Características do MIPS
• Pipeline: O MIPS foi projetado para ter um pipeline de instruções
eficiente, o que significa que pode começar a processar uma nova
instrução antes de terminar a anterior.
• Conjunto de instruções: O MIPS tem um conjunto de instruções
simples e regular, o que o torna ideal para a pipelining.
• Registradores: O MIPS tem 32 registradores de propósito geral
• Endereçamento: O MIPS suporta vários modos de endereçamento,
incluindo imediato, base + deslocamento e endereçamento de
registro
Aula 2: Registradores em
MIPS
Função e propósito dos registradores:
• Os registradores são pequenas unidades de armazenamento
localizadas dentro da CPU.
• Eles são usados para armazenar dados temporariamente durante a
execução de instruções. Em MIPS, os registradores são essenciais para
operações aritméticas, acesso à memória e controle de fluxo.
• Rápido acesso: Os registradores fornecem acesso mais rápido aos
dados do que a memória principal
• Eficiência: Usar registradores reduz a necessidade de acessos
frequentes à memória, tornando a execução do programa mais
eficiente..
Tipos de registradores em MIPS
• $zero: Este registrador sempre contém o valor 0. É útil para operações
que requerem o valor zero sem ter que carregá-lo de outro lugar.
• $at (Assembler Temporary): Reservado para uso pelo montador.
• $v0-$v1 (Values): Usados para retornar valores de funções.
• $a0-$a3 (Arguments): U.sados para passar argumentos para funções.
Se uma função tem mais de quatro argumentos, os argumentos
adicionais são passados na pilha.
• $t0-$t9 (Temporaries): Registradores temporários que não precisam
ser salvos em chamadas de função. O compilador pode usar esses
registradores como bem entender.
• $s0-$s7 (Saved): Registradores que precisam ser salvos em chamadas
de função. Se um programa usa um desses registradores e chama
uma função, ele deve salvar o valor do registrador antes de chamar a
função e restaurá-lo após a função retornar.
• $k0-$k1 (Kernel): Reservado para uso pelo sistema operacional
• $gp (Global Pointer): Aponta para o meio do segmento de dados
global. É usado para acessar dados globais.
• $sp (Stack Pointer): Aponta para o topo da pilha na memória.
• $fp (Frame Pointer): Usado para acessar os dados na pilha em relação
ao início do quadro atual.
• $ra (Return Address): Contém o endereço para retornar após uma
chamada de função. É definido pela instrução `jal` (jump and link).
• Os registradores em MIPS são fundamentais para a execução eficiente
de programas. Eles permitem que a CPU armazene e acesse
rapidamente os dados necessários para operações, reduzindo a
necessidade de acessos frequentes à memória.
Aula 3: Operações Básicas em
MIPS
1. Instruções de soma e subtração
• add: Esta é a instrução básica de adição em MIPS. Ela soma dois
registradores e armazena o resultado em um terceiro registrador.
• Formato: add $dest, $src1, $src2
• Exemplo: add $t0, $t1, $t2 (Isso somará os valores em $t1 e $t2 e
armazenará o resultado em $t0)
• addi (Add Immediate): Esta instrução soma um valor imediato a um
registrador e armazena o resultado em um segundo registrador.
• Formato: addi $dest, $src, immediate
• Exemplo: addi $t0, $t1, 5 (Isso adicionará 5 ao valor em $t1 e
armazenará o resultado em $t0)
• sub: Esta é a instrução básica de subtração em MIPS. Ela subtrai o
valor de um registrador de outro registrador e armazena o resultado
em um terceiro registrador.
• Formato: sub $dest, $src1, $src2
• Exemplo: sub $t0, $t1, $t2 (Isso subtrairá o valor em $t2 do valor em
$t1 e armazenará o resultado em $t0)
2. Uso de imediatos com addi
• Os imediatos são valores constantes especificados diretamente nas
instruções. Em MIPS, a instrução `addi` é frequentemente usada com
imediatos para adicionar um valor constante a um registrador.
• Isso é útil para operações como incrementar um registrador ou
adicionar um deslocamento a um endereço.
3. Diferença entre operações aritméticas e
lógicas
• Operações Aritméticas: Estas são operações que lidam com números
e são usadas para cálculos matemáticos. Exemplos incluem adição,
subtração, multiplicação e divisão. Em MIPS, instruções como `add`,
`sub`, `mul` e `div` são operações aritméticas.
• Operações Lógicas: Estas são operações que lidam com valores
booleanos (verdadeiro ou falso) e são usadas para testes e
comparações. Exemplos incluem AND, OR, NOT e XOR. Em MIPS,
instruções como `and`, `or`, `nor` e `xor` são operações lógicas.
• A principal diferença entre as duas é o tipo de operação que elas
realizam. Enquanto as operações aritméticas são usadas para cálculos
matemáticos, as operações lógicas são usadas para operações de bit a
bit e comparações.
4. Operações com imediato
• Todas as funções que utilizam 3 registradores (tipo R) tem sua versão
com imediato (tipo I).
• Assim como add tem addi, temos subi, andi, xori, ori entre outras.
Aula 4: Acesso à Memória
em MIPS
1. Instruções lw (load word) e sw (store word)
• lw (Load Word): Esta instrução é usada para carregar uma palavra (32
bits) da memória para um registrador.
• Formato: lw $dest, offset($base)
• Exemplo:lw $t0, 4($t1) (Isso carregará a palavra da memória no endereço `$t1
+ 4` para o registrador `$t0`)
• sw (Store Word): Esta instrução é usada para armazenar uma palavra
de um registrador na memória.
• Formato: sw $src, offset($base)
• Exemplo: sw $t0, 4($t1) (Isso armazenará a palavra no registrador `$t0` na
memória no endereço `$t1 + 4`)
2. Endereçamento de memória e uso do
registrador $gp (ponteiro global)
• O MIPS utiliza um modelo de memória linear, onde cada local de
memória tem um endereço único.
• O endereçamento de memória é frequentemente feito usando um
registrador base e um deslocamento.
• Registrador Base: É o registrador que contém o endereço base da
memória
• Deslocamento: É um valor imediato que é adicionado ao endereço
base para obter o endereço final de memória.
• O registrador `$gp` (ponteiro global) é usado em MIPS para acessar dados
globais. Ele aponta para o meio do segmento de dados global, tornando
mais fácil acessar variáveis globais e estáticas.
• Uso do $gp: O `$gp` é frequentemente usado como o registrador base em
instruções `lw` e `sw`.
• Por exemplo, se uma variável global está localizada a 20 bytes do início do
segmento de dados global, você pode usar `lw $t0, 20($gp)` para carregar
essa variável no registrador `$t0`.
• O acesso à memória é uma parte fundamental da programação em
assembly, pois permite que os programas leiam e escrevam dados na
memória. Em MIPS, as instruções `lw` e `sw` tornam esse processo simples
e eficiente.
Aula 5: Vetores
Vetores (ou arrays) são uma estrutura de dados fundamental que
permite armazenar uma coleção de itens do mesmo tipo em uma única
variável. Em MIPS, os vetores são representados como blocos contíguos
de memória. Vamos explorar como eles são usados e manipulados em
assembly MIPS.
1. Declaração e Inicialização de Vetores
• Em MIPS, um vetor é geralmente declarado reservando espaço na seção de
dados.
• Por exemplo, para declarar um vetor de 4 inteiros:
.data
myArray: .space 16 # Reserva 16 bytes (4 inteiros de 4 bytes cada)

Ou, para inicializar um vetor com valores específicos:

.data
myArray: .word 10, 20, 30, 40 # Inicializa o vetor com 4 inteiros
2. Acessando Elementos do Vetor
#myArray[2]
la $t0, myArray # Carrega o endereço base do vetor em $t0
li $t1, 2 # Índice do elemento desejado
add $t1,$t1,$t1
add $t1,$t1,$t1 # Calcula o deslocamento
add $t0, $t0, $t1 # Adiciona o deslocamento ao endereço base
lw $t3, 0($t0) # Carrega o terceiro elemento do vetor em $t3
3. Modificando Elementos do Vetor
• Para modificar um elemento, você segue um processo semelhante ao de
acessar um elemento, mas usa a instrução `sw` (store word) para
armazenar um novo valor no vetor.
• Exemplo: Para definir o terceiro elemento de um vetor de inteiros para 50:

la $t0, myArray # Carrega o endereço base do vetor em $t0


li $t1, 2 # Índice do elemento desejado
sll $t1,$t1, 2 # Calcula o deslocamento
add $t0, $t0, $t1 # Adiciona o deslocamento ao endereço base
li $t3, 50 # Valor a ser armazenado
sw $t3, 0($t0) # Armazena 50 no terceiro elemento do vetor
4. Iterando sobre um Vetor
• Para iterar sobre um vetor, você pode usar um laço, incrementando o
endereço do vetor pelo tamanho do tipo de dado a cada iteração.
• Vetores em MIPS, assim como em outras linguagens de programação,
são uma ferramenta essencial para armazenar e manipular coleções
de dados.
• Compreender como declarar, acessar e modificar vetores é
fundamental para a programação eficaz em assembly.
Aula 6: Controle de Fluxo em
MIPS
1. Instruções de branch:
• As instruções de branch são usadas para alterar o fluxo de execução
do programa com base em uma condição. Em MIPS, as instruções de
branch mais comuns são `beq` e `bne`.

• beq (Branch if Equal): Esta instrução verifica se dois registradores são


iguais. Se forem, o programa salta para um endereço especificado.
Formato: beq $src1, $src2, label
Exemplo: beq $t0, $t1, SomeLabel (Se `$t0` for igual a `$t1`, o programa saltará
para `SomeLabel`)
• bne (Branch if Not Equal): Esta instrução verifica se dois registradores
são diferentes. Se forem, o programa salta para um endereço
especificado.
• Formato: bne $src1, $src2, label
• Exemplo: bne $t0, $t1, SomeLabel (Se `$t0` for diferente de `$t1`, o programa
saltará para `SomeLabel`)
2. Instrução j (jump) para saltos
incondicionais
• A instrução `j` é usada para saltos incondicionais, o que significa que
ela sempre fará o programa saltar para um endereço especificado,
independentemente de qualquer condição.

• - j (Jump): Esta instrução faz o programa saltar para um endereço ou


etiqueta especificada.
• Formato: j label
• Exemplo: j SomeLabel (O programa saltará incondicionalmente para
`SomeLabel`)
3. Comparação com condicionais - slt (Set on
Less Than):
• A instrução `slt` compara dois registradores e, se o primeiro
registrador for menor que o segundo, ela define um terceiro
registrador para 1. Caso contrário, o terceiro registrador é definido
como 0.
• Formato: slt $dest, $src1, $src2
• Exemplo: slt $t0, $t1, $t2
• Se o valor em `$t1` for menor que o valor em `$t2`, então `$t0` será definido
como 1. Caso contrário, `$t0` será definido como 0.
• A instrução `slt` também pode ser usada com valores imediatos
através da instrução `slti`.

• Formato: slti $dest, $src, immediate


• Exemplo: slti $t0, $t1, 10
• Se o valor em `$t1` for menor que 10, então `$t0` será definido como 1. Caso
contrário, `$t0` será definido como 0.
Como usar SLT com instruções de branch
• A instrução `slt` é frequentemente usada em conjunto com `beq` ou
`bne` para implementar comparações maiores que, menores que ou
iguais.
• Exemplo de uso para verificar se `$t1` é menor que `$t2`:

slt $t0, $t1, $t2


beq $t0, $zero, fim
add $t1,$t1,$t2
fim:
• Exemplo de uso para verificar se `$t1` é maior ou igual a `$t2`:

slt $t0, $t1, $t2


bne $t0, $zero, fim
add $t1,$t1,$t2
fim:
Aula 7: Laços em MIPS
• 1. Laço FOR:

• Em linguagens de alto nível, um laço `for` tem uma inicialização, uma


condição e uma atualização. Em assembly, isso é implementado
usando instruções de inicialização, seguido por uma verificação de
condição e um bloco de código que é repetido.
For • Implementação em MIPS:

• Exemplo de um laço for em C: li $t0, 0 # i = 0 (inicialização)


for(i = 0; i < 10; i++) { Loop: beq $t0, 10, FIM # Se i == 10, saia
do laço
// código do laço
# código do laço aqui
}
addi $t0, $t0, 1 # i++ (atualização)
j Loop # Volte para o início do laço
FIM: # Continuação do código
2. Laço WHILE
Exemplo de um laço WhileLoop:
while em C: beq $t0, 10, EndOfWhile # Se i == 10, saia do
while(i < 10) { laço
// código do laço # código do laço aqui
}
j WhileLoop # Volte para o início do laço
EndOfWhile:
# Continuação do código
3. Uso de instruções de branch para controle de
laços
• As instruções de branch, como `beq` e `bne`, são essenciais para
implementar laços em assembly.
• Elas permitem que o programa decida se deve continuar no laço ou
sair dele.
beq: Usado para verificar a condição de saída do laço.
bne: Pode ser usado para verificar a condição de continuação do laço.

• Além das instruções de branch, a instrução `j` (jump) é usada para


fazer o programa voltar ao início do laço após cada iteração.
Aula 8: Funções em MIPS
Aula 8: Funções em MIPS
• 1. Chamada e retorno de funções:
• jal (Jump and Link): Esta instrução é usada para chamar uma função.
Ela salta para o endereço da função e salva o endereço da próxima
instrução no registrador `$ra` (return address).
• Formato: jal FunctionLabel

• jr (Jump Register): Esta instrução é usada para retornar de uma


função. Ela salta para o endereço especificado no registrador
fornecido, geralmente `$ra`.
• Formato: jr $ra
2. Convenções de chamada
• Passagem de Argumentos: Os argumentos para funções são
geralmente passados nos registradores `$a0-$a3`. Se houver mais de
quatro argumentos, os argumentos adicionais são passados na pilha.

• Valores de Retorno: Os valores de retorno das funções são


geralmente colocados nos registradores `$v0` e `$v1`.
3. Uso do registrador $ra (return address) e
pilha
• $ra (Return Address): Quando uma função é chamada usando `jal`, o
endereço da próxima instrução é automaticamente salvo no
registrador `$ra`. Este endereço é usado para retornar da função
usando a instrução `jr`.
• Pilha: A pilha é usada para salvar o estado atual antes de chamar uma
função. Isso inclui salvar quaisquer registradores que a função possa
alterar (como `$ra` e registradores temporários) e quaisquer
argumentos adicionais. Após a execução da função, o estado é
restaurado da pilha.
• Push: Para adicionar (ou "empurrar") um valor na pilha, você
decrementa o ponteiro da pilha (`$sp`) e, em seguida, armazena o
valor no topo da pilha.
• Pop: Para remover (ou "retirar") um valor da pilha, você carrega o
valor do topo da pilha e, em seguida, incrementa o ponteiro da pilha.
Exemplo de chamada de função em MIPS
main:
# Passar argumentos addNumbers:
li $a0, 5 # Adicionar números
li $a1, 10 add $v0, $a0, $a1

# Chamar função
jal addNumbers # Retornar
jr $ra
# Continuar execução
após chamada de função
...

Você também pode gostar