Arquitectura de Computadores ARQC MIPS Serviços de Sistemas Exemplos Serviços de Sistema Exemplo 1 Fonte: http://usuarios.upf.br/~brusso/arq2/spim.html Somar duas variáveis em um registrador Código em C register int a=1, b=3, c; c = a + b; Código em linguagem de montagem MIPS (usar os có códigos de serviç serviço) # exe1.s - Soma duas variáveis em um registrador .text .globl __start __start: li $t0, 1 # $t0 = 1 li $t1, 3 # $t1 = 3 add $t2, $t1, $t0 # $t2 = $t1 + $t0 li $v0, 10 # Serviço 10 : Exit syscall Exemplo 2 Fonte: http://usuarios.upf.br/~brusso/arq2/spim.html Somar duas variáveis na memória Código em C Código em linguagem de montagem MIPS static int va=0, vb=5, vc=10; a = b + c; # exe2.s soma duas variaveis na memoria # segmento de dados .data va: .word 0 vb: .word 5 vc: .word 10 # segmento de texto .text .globl __start __start: lw $t0, vb # Carrega vb em $t0 lw $t1, vc # Carrega vc em $t1 add $t2, $t1, $t0 # $t2 = $t1 + $t0 sw $t2, va # Armazena $t2 em va li $v0, 10 # Serviço 10 : exit syscall Exemplo 3 Fonte: http://usuarios.upf.br/~brusso/arq2/spim.html Ler um número inteiro Código em C printf("Digite um numero:"); var = read_int(); Código em linguagem de montagem MIPS # ex3.s - Ler um número inteiro .data aviso: .asciiz "Digite um numero:" .text .globl __start __start: la $a0, aviso # Carrega endereco da string em $a0 li $v0, 4 # Serviço 4 : imprime string syscall li $v0, 5 # Serviço 5 : lê inteiro syscall add $t1, $t1, $v0 # $t1 = $v0 li $v0, 10 # Serviço 10 : exit syscall Exemplo 4 Execução condicional Código em C if(var1<5){ var2 = var2 + var1; var1 = 0; } else var2 = var2 + 1; Código em linguagem de montagem MIPS Fonte: http://usuarios.upf.br/~brusso/arq2/spim.html # ex4.s – Execução condicional .data var1: .word 1 var2: .word 5 .text .globl __start __start: lw $s0, var1 # carrega var1 lw $s1, var2 # carrega var2 slti $t0, $s0, 5 # testa se var1 < 5 beq $t0, $zero, senao # se falso, pula p/ senao add $s1, $s1, $s0 # var2 = var2 + var1 li $s0, 0 # var1 = 0 sw $s0, var1 # armazena var1 sw $s1, var2 # armazena var2 j fim_se # pula p/ fim senao: addi $s1, $s1, 1 # var2 = var2 + 1 sw $s1, var2 # armazena var2 fim_se: li $v0, 10 # exit syscall Exemplo 5 Manipulação de Vetores Código em C int vetor[] = {10, 5, 8, 20, 43}; int i=0; do{ printf("%d\n", vetor[i]); i++; } while(i<5); Código em linguagem de montagem MIPS Fonte: http://usuarios.upf.br/~brusso/arq2/spim.html # ex5.s – Manipulação de Vetores .data vetor: .word 10, 5, 8, 20, 43 linha: .asciiz "\n" .text .globl __start __start: la $t0, vetor # endereco do vetor li $t1, 0 #i laco: li $v0, 1 # imprime inteiro lw $a0, 0($t0) # valor a imprimir syscall li $v0, 4 # imprime string la $a0, linha # nova linha syscall addi $t0, $t0, 4 # proximo endereco addi $t1, $t1, 1 # proximo i blt $t1, $t2, laco # ir p/ laco se $t1<$t2 li $v0, 10 # termina syscall Chamada de Procedimentos • Quando uma função deve ser chamada, deve-se salvar os parâmetros a serem passados a funções nos registradores $a0-$a3 e chamar a função usando a instrução jal (jump-and-link) – O conteúdo de PC + 4 será salvo no registrador $ra de tal modo que ao final da função uma chamada jr $ra fará com que o programa execute a instrução posterior àquela que chamou a função. • Mais de quatro parâmetros podem ser passados usando uma pilha LIFO (Last In Fisrt Out) – MIPS mantém um registrador, o $sp (Stack Pointer) para manter o endereço do topo da pilha • Convenção para a pilha (motivos históricos): • Operação Push (inserir dados na pilha): endereço da pilha diminui ($sp-x) • Operação Pop (retirar dados da pilha): endereço da pilha aumenta ($sp+x) • Para o retorno do cálculo realizado no função, os registradores $v0-$v1 devem ser utilizados Exemplo 6 Fonte: http://usuarios.upf.br/~brusso/arq2/spim.html Chamada de procedimento 1 Código em C Código em linguagem de montagem MIPS void main(void) { int va, vb; va = cubo(2); vb = cubo(va); } int cubo(int num) { int temp; temp = num*num*num; return(temp); } • $a0-$a3 = registradores de argumentos para passagem de parâmetros • $v0-$v1 = registradores de valor para valores de retorno • $ra = registrador de endereço de retorno (partida + 1 => PC + 4) # ex6.s – Chamada de procedimento .text .globl __start # Função main() __start: li $a0, 2 # Passa valor 2 como parâmetro jal cubo # Chama procedimento cubo move $s0, $v0 # Atribui valor de retorno p/ va move $a0, $s0 # Passa va como parâmetro jal cubo # Chama procedimento cubo move $s1, $v0 # Atribui valor de retorno p/ vb li $v0, 10 # Servico 10: exit syscall # Função cubo() cubo: mul $t0, $a0, $a0 mul $t0, $t0, $a0 move $v0, $t0 jr $ra # # # # temp = num * num temp = temp * num Define valor de retorno Retorna do procedimento Exercício 7 Chamada de procedimento 2: comente o código apresentado. Código em C main() { x = soma3(a, b, c) } soma3(x, y, z) { return( soma( x, soma(y, z))); } soma(x1, x2) { return( x1+x2 ); } # ex7.s: Subrotinas aninhadas # Author: Fernando Gehm Moraes .text .globl __start Código em linguagem __start: la $s1, var_a de montagem MIPS lw $s1, 0($s1) la $s2, var_b lw $s2, 0($s2) la $s3, var_c lw $s3, 0($s3) addiu $sp,$sp,-16 sw $ra, 0($sp) sw $s1, 4($sp) sw $s2, 8($sp) sw $s3,12($sp) jal soma3 lw $ra,0($sp) lw $s4,4($sp) addiu $sp,$sp,16 end: j $ra Exercício 7 Fonte: http://usuarios.upf.br/~brusso/arq2/spim.html Chamada de procedimento: comente o código apresentado M soma3: lw $t0, 4($sp) lw $t1, 8($sp) M sw addiu $sp,$sp,-12 sw $ra, 0($sp) sw $t0, 4($sp) sw $t1, 8($sp) jal soma lw $ra,0($sp) lw $t0,4($sp) addiu $sp,$sp,12 lw $t1, 12($sp) addiu $sp,$sp,-12 sw $ra,0($sp) sw $t0,4($sp) sw $t1,8($sp) jal soma lw $ra,0($sp) lw $t0,4($sp) addiu $sp,$sp,12 j $t0,4($sp) $ra soma: lw $t7,4($sp) lw $t8,8($sp) addu $t7,$t7,$t8 sw $t7,4($sp) jr $ra .data var_a: .word 0x00AA0000 var_b: .word 0x0000BB00 var_c: .word 0x000000CC # Final do arquivo Exercícios 1. Multiplicar dois números usando o seguinte procedimento: 1. 2. 3. 4. 5. Carrega o valor de A em $s0 (0x01234ABC ) Carrega o valor de B em $s1 (0x004A5F32 ) Zerar o registrador $s2 que conterá o resultado (dica: usar xor) Carrega o registrador $t0 com 1, para servir como máscara para comparação Verifica se B ($s1) for zero. 1. Se afirmativo terminou a multiplicação, salta para passo 10 6. verifica se o bit menos significativo de B ($s1) e' igual a '1' ($t0) 1. Se afirmativo acumula o resultado ($s2) com A ($s0) 7. Desloca B ($s1) um bit para a direita 8. Desloca A ($s0) um bit para a esquerda 9. Volta para o passo 5 10. Grava o conteúdo de $s2 no endereço res 2. Melhorar o programa anterior permitindo que o usuário forneça o valor de cada operando. Garantir que após o cálculo, os dados sejam apresentados ao usuário. 3. Escreva uma função que calcule o fatorial de um número. Escreva então um programa que solicite que o usuário introduza um valor e que na seqüência chame a função fatorial, calcule o fatorial do número e o apresente ao usuário.