Você está na página 1de 14

Escola de Engenharia

Universidade Federal de Minas Gerais (UFMG)


ELT123 - Arquitetura e Organização de Computadores

Tópico 5: Arquitetura (Matrizes)

Prof. Jhonattan Cordoba Ramirez


Vetor
Matrizes Primeiro Elemento
índice No índice 8

As Matrizes são úteis para se acessar grandes 0 1 2 3 4 5 6 7 8 9 Índices


quantidades de dados similares. Uma Matriz é
organizado como endereços sequenciais de dados Comprimento total da matriz é 10
na memória.
Índice: Acesso à cada elemento
Tamanho ou comprimento: Numero de elementos 0x12348010 Matriz[4]
0x1234800C Matriz[3]
0x12348008 Matriz[2]
•Matriz de 5 elementos 0x12348004 Matriz[1]
0x12348000 Matriz[0]
•Endereço base = 0x12348000 (endereço do primeiro
elemento, matriz [0])
•Primeiro passo para acessar uma matriz: carregar o
endereço base em um registro.

Matriz?
Matrizes
// Código em C
int array[5];
array[0] = array[0] * 2;
array[1] = array[1] * 2;

# Código MIPS Assembly


# $s0 = Endereço base da matriz
lui $s0, 0x1234 # 0x1234 na metade superior de $s0
ori $s0, $s0, 0x8000 # 0x8000 na metade inferior de $s0
lw $t1, 0($s0) # $t1 = array[0]
sll $t1, $t1, 1 # $t1 = $t1 * 2
sw $t1, 0($s0) # array[0] = $t1
lw $t1, 4($s0) # $t1 = array[1]
sll $t1, $t1, 1 # $t1 = $t1 * 2
sw $t1, 4($s0) # array[1] = $t1
Matrizes usando loop FOR!

loop:
slt $t0, $s1, $t2 # i < 1000?
Código MIPS Assembly beq $t0, $0, done # if not then done
Código em C
# $s0 = array base address, $s1 = i sll $t0, $s1, 2 # $t0 = i * 4 (byte
int array[1000];
# initialization code offset)
int i;
lui $s0, 0x23B8 # $s0 = 0x23B80000 add $t0, $t0, $s0 # address of array[i]
for (i=0; i < 1000; i = i + 1)
ori $s0, $s0, 0xF000 # $s0 = 0x23B8F000 lw $t1, 0($t0) # $t1 = array[i]
array[i] = array[i] * 8;
addi $s1, $0, 0 #i=0 sll $t1, $t1, 3 # $t1 = array[i] * 8
addi $t2, $0, 1000 # $t2 = 1000 sw $t1, 0($t0) # array[i] = array[i] * 8
addi $s1, $s1, 1 #i=i+1
j loop # repeat
done:

Multiplicação de valores ímpares?


Informação complementar

Registros especiais: lo, hi


Multiplicação 32 × 32, resultado de 64 bits
mult $s0, $s1 -- Resultado em {hi, lo}

Divisão de 32 bits, quociente de 32 bits, restante


div $s0, $s1 -- Quociente em lo e restante em hi

Para mover os resultados armazenados nos registros


especiais lo, hi usamos:
mflo $s2
mfhi $s3
Funções

Linguagens de alto nível frequentemente utilizam funções (também chamadas procedimentos) para reutilizar
códigos frequentemente acessados e também para fazer um programa mais modular e legível. As funções
possuem entradas, chamadas argumentos, e uma saída, chamada valor de retorno. As funções calculam o
valor de retorno e não causam outros efeitos colaterais indesejáveis.
Quando uma função chama outra, a função chamadora e a função chamada devem concordar em onde colocar
os argumentos e os valores de retorno.

• A função chamada não deve interferir na função chamadora: A função Argumento:


chamada, deve saber onde voltar depois de finalizar sua execução. • $a0 - $a3
• A função chamadora, usa a função Jump and Link (jal) - “salto e conexão” Valor de retorno:
para pular diretamente para a função chamada. • $v0 - $v3
• Ao mesmo tempo a função chamadora armazena o endereço de retorno no
registrador $ra.
Chamadas de funções

Chamador: função principal que realiza a ação de


Código em C
chamar (neste caso, principal)
void main()
• Passa argumentos à função chamada
{
• Pula para a função chamada
int y;
Chamado (Callee): Função externa que é chamada pela
y = sum(42, 7);
função principal (neste caso, soma)
...
• A função é executada
}
• Retorna o resultado obtido para a função
int sum(int a, int b)
chamador
{
• Retorna para o ponto de chamada
return (a + b);
• Não sobrescreve registros ou memoria necessária
}
para a execução do chamador.
Chamadas de funções

Código em C Código MIPS Assembly


int main() { 0x00400200 main:
simple(); jal simple
a = b + c; 0x00400204 add $s0, $s1, $s2
Função de chamada: salto e link (jal)
} ...
Retorno à função inicial: jump register
void simple() { 0x00401020 simple:
(jr)
return; jr $ra
Argumentos: $a0 - $a3
}
Valores de retorno: $ v0 - $v3
jal: salto simples
$ra = PC + 4 = 0x00400204
jr $ra: pular para endereço em $ra (0x00400204)
Exemplo
Código em C
int main()
Código MIPS Assembly
{
# $s0 = y
int y;
main: # $s0 = result
...
... diffofsums:
y = diffofsums(2, 3, 4, 5); // 4 arguments
addi $a0, $0, 2 # argumento 0 = 2 add $t0, $a0, $a1 # $t0 = f + g
...
addi $a1, $0, 3 # argumento 1 = 3 add $t1, $a2, $a3 # $t1 = h + i
}
addi $a2, $0, 4 # argumento 2 = 4 sub $s0, $t0, $t1 # result = (f + g) - (h + i)
int diffofsums(int f, int g, int h, int i)
addi $a3, $0, 5 # argumento 3 = 5 add $v0, $s0, $0 # valor de retorno em
{
jal diffofsums # Chamar função $v0
int result;
add $s0, $v0, $0 # y = Valor retornado jr $ra # voltar para o chamador
result = (f + g) - (h + i);

return result; // return value
} Quando uma função com mais de quatro argumentos é chamada, os
argumentos adicionais de entrada são colocados na pilha
Pilha (Stack)

Código MIPS Assembly


• Stack (Pilha)
# $s0 = result
• Memória usada para salvar
diffofsums:
temporariamente variáveis
add $t0, $a0, $a1 # $t0 = f + g
• Funciona como uma pilha de pratos. Pilha
add $t1, $a2, $a3 # $t1 = h + i
• LIFO (last-in-first-out)
sub $s0, $t0, $t1 # resultado = (f + g) - (h + i)
• Expande: usa mais memória quando mais
add $v0, $s0, $0 # Valor de retorno em $v0
espaço é necessário
jr $ra # return to caller
• Contratos: usa menos memória quando o
diffofsums: Sobrescreveu três registradores $t0,$t1 e
espaço não é mais necessário
$s0.
diffofsums: Pode usar Pilha (stack) para armazenar de
forma temporária registradores.
Valor no registrador armazenado na pilha
# $s0 = result
Armazenamento da pilha é feita de forma
diffofsums:
descendente (do endereço de memória mais
addi $sp, $sp, -12 # fazer espaço no stack
alto para o mais baixo). para armazenar 3 registradores.
Ponteiro da pilha: $sp aponta para o topo sw $s0, 8($sp) # salvar $s0 no stack
da pilha sw $t0, 4($sp) # salvar $t0 no stack
sw $t1, 0($sp) # salvar $t1 no stack
7FFFFFFC 12345678 $sp add $t0, $a0, $a1 # $t0 = f + g
7FFFFFF8 …
add $t1, $a2, $a3 # $t1 = h + i
7FFFFFF4 …
sub $s0, $t0, $t1 # resultado = (f + g) - (h + i)
add $v0, $s0, $0 # valor de retorno em $v0
lw $t1, 0($sp) # restaurar $t1 do stack
7FFFFFFC 12345678
lw $t0, 4($sp) # restaurare $t0 do stack
7FFFFFF8 AABBCCDD
lw $s0, 8($sp) # restaurar $s0 do stack
7FFFFFF4 112342AF
$sp addi $sp, $sp, 12 # libertar stack
jr $ra # retornar ao chamadorr
Resumo de chamada de funções

• Chamadora • Chamada
• Coloque argumentos em $ a0- $ a3 • Salve os registros que podem estar com
• Salve todos os registros necessários ($ ra, talvez problemas ($s0 - $s7 ou $t0 - $t9)
$ $t0 - $t9 ou $s0 - $s7 ) • Executar função
• jal callee • Coloque o resultado em $v0
• Restaurar registros • Restaurar registros
• Procure resultado em $ v0 • jr $ra
Exercício

High-level code
int factorial(int n)
{
if (n <= 1)
return 1;
else
return (n * factorial(n-1));
}

Você também pode gostar