Programação em assembly Variáveis não-estruturadas reservar registos sempre que possível restantes variáveis em memória Exemplo int d, a=100, c=10, d=15; main () { d = a / (c + d); } .text li $s0, 100 # a=100 li $s1, 10 # c=10 li $s2, 15 # d=15 add $t0, $s1, $s2 div $s2, $s0, $t0 # d = a/(c +d) jr $ra div $s0, $t0 mflo $s2 Pseudo-instruções addi $s0, $0, 100 23-02-2019 Arquitectura de Computadores
Programação em assembly Estruturas de controlo de fluxo: if .. then .. else .. Exemplo int a,b,c; main () { if (a==b) c = c+1; else c = c-1; } .text bne $s0, $s1, else # a==b ??? addi $s2, $s2, 1 # c = c+1 b fim else: addi $s2, $s2, -1 fim: jr $ra Pseudo-instrução beq $0, $0, fim 23-02-2019 Arquitectura de Computadores
Programação em assembly Estruturas de controlo de fluxo: if .. then .. else .. Exemplo int a,b,c; main () { if (a>=b) c = c+1; else c = c-1; } .text blt $s0, $s1, else # a<b ??? addi $s2, $s2, 1 # c = c+1 b fim else: addi $s2, $s2, -1 fim: jr $ra Pseudo-instrução slt $at, $s0, $s1 bne $at, $0, else 23-02-2019 Arquitectura de Computadores
Programação em assembly Estruturas de controlo de fluxo: while (..) {.. } Exemplo int a,b; main () { while (a>b) a++; } .text ciclo: ble $s0, $s1, fim # a>b ??? addi $s0, $s0, 1 # a = a+1 b ciclo fim: jr $ra Pseudo-instrução slt $at, $s1, $s0 beq $at, $0, fim Optimização .text b fim ciclo: addi $s0, $s0, 1 fim: bgt $s0, $s1, ciclo jr $ra 23-02-2019 Arquitectura de Computadores
Programação em assembly Estruturas de controlo de fluxo: for (..;..;..) {.. } Exemplo int a,b,i; main () { for (i=0 ; i<a ; i++) b = b + a; } .text li $t0, 0 ciclo: bge $t0, $s0, fim # i<a ??? add $s1, $s1, $s0 # b = b+a addi $t0, $t0, 1 # i++ b ciclo fim: jr $ra Pseudo-instrução slt $at, $t0, $s0 beq $at, $0, fim Poder-se-á aplicar uma optimização semelhante à do exemplo anterior? 23-02-2019 Arquitectura de Computadores
Programação em assembly Variáveis estruturadas: arrays XXXX Endereço base [0] Deslocamento = índice * factor de escala XXXX+4 [1] XXXX+8 [2] 23-02-2019 Arquitectura de Computadores
Programação em assembly Variáveis estruturadas: arrays Exemplo int a[10],i; main () { for (i=0 ; i<10 ; i++) a[i] = a[i] + 5; } .text li $t0, 0 la $t1, a ciclo: bge $t0, 10, fim # i<10 ??? add $t2, $t0, $t0 # $t2 = i*2 add $t2, $t2, $t2 # $t2 = i*4 add $t2, $t1, $t2 lw $t3, 0($t2) addi $t3, $t3, 5 sw $t3, 0($t2) # a[i]=a[i]+5 addi $t0, $t0, 1 # i++ b ciclo fim: jr $ra 23-02-2019 Arquitectura de Computadores
Programação em assembly Variáveis estruturadas: arrays Acesso com apontadores Exemplo int a[10], *ptr; main () { for (ptr=a ; ptr<a+10 ; ptr++) *ptr = *ptr + 5; } .text la $t0, a # ptr = a la $t1, a addi $t1, $t1, 40 # controlo do ciclo ciclo: bge $t0, $t1, fim # ptr < a+10 ??? lw $t2, 0($t0) addi $t2, $t2, 5 sw $t2, 0($t0) # *ptr = *ptr + 5 addi $t0, $t0, 4 # ptr++ b ciclo fim: jr $ra 23-02-2019 Arquitectura de Computadores
Programação em assembly Variáveis estruturadas: estruturas Exemplo struct { double frac; int cnt; } a[10]; int i; main () { for (i=0 ; i<10 ; i++) a[i].cnt = a[i].cnt + 5; } .text li $t0, a # i = 0 la $t1, a ciclo: bge $t0, 10, fim # i < 10 ??? mul $t2, $t0, 12 # factor de escala add $t2, $t1, $t2 lw $t3, 8($t2) # offset = 8 addi $t3, $t3, 5 sw $t3, 8($t2) addi $t0, $t0, 1 # i++ b ciclo fim: jr $ra 23-02-2019 Arquitectura de Computadores
Programação em assembly Stack Estrutura de dados mantida em memória, utilizada para manter dados com caracter temporário O registo $sp aponta para o início da última palavra colocada na stack A stack cresce de endereços mais altos para endereços mais baixos AAAA AAAA+4 $sp Push subu $sp, $sp, 4 sw $t0, 0($sp) Pop lw $t0, 0($sp) add $sp, $sp, 4 23-02-2019 Arquitectura de Computadores
Programação em assembly Procedimentos e funções Passos na execução de uma função: Passagem de parâmetros Utilização de registos ($a0....$a3) Stack para os restantes Transferência de controlo jal <label> Aquisição de recursos de memória para variáveis locais Salvaguardar os registos utilizados Stack para variáveis adicionais Execução da rotina Retorno do resultado Registos ($v0, $v1) Transferência de controlo Reposição de registos jr $ra 23-02-2019 Arquitectura de Computadores
Programação em assembly Procedimentos e funções Vamos analisar o seguinte exemplo, tendo em conta que main também é uma função e que as várias funções podem ser codificadas separadamente. main () { int a, b, c; a = 10; b = 15; c = multi (a, b); ... } int multi (int m0, int m1) { int i, res; res = 0; for (i=0 ; i<m1 ; i++) res = res + m0; return (res); 23-02-2019 Arquitectura de Computadores
Programação em assembly Procedimentos e funções Solução: todos os registos têm que ser salvaguardados .text main: sub $sp, $sp, 20 sw $ra, 16($sp) sw $v0, 12($sp) sw $a0, 8($sp) sw $a1, 4($sp) sw $t0, 0($sp) li $a0, 10 # a=10 li $a1, 15 # b=15 jal multi move $t0, $v0 ... lw $t0, 0($sp) lw $a1, 4($sp) lw $a0, 8($sp) lw $a1, 12($sp) lw $ra, 16($sp) addi $sp, $sp, 20 jr $ra multi: sub $sp, $sp, 4 sw $t0, 0($sp) li $v0, 0 # res=0 li $t0, 0 # i=0 ciclo: bge $t0, $a1, fim add $v0, $v0, $a0 addi $t0, $t0, 1 b ciclo fim: lw $t0, 0($sp) addi $sp, $sp, 4 jr $ra 23-02-2019 Arquitectura de Computadores
Programação em assembly Procedimentos e funções Na solução anterior são guardados em memória 6 registos, o que implica penalizações com acessos à memória Convenciona-se que: os registos $t podem ser utilizados pelas funções sem que precisem de os salvaguardar os registos $s, se alterados, são sempre salvaguardados os registos $a e $v podem ser utilizados sem salvaguardar NOTA: Se uma função invoca outra e tem nos registos $t, $v, $a ou $ra valores de que necessita, então é a função invocadora a responsável por guardar estes valores. 23-02-2019 Arquitectura de Computadores
Programação em assembly Procedimentos e funções Solução: utilizando a convenção .text main: sub $sp, $sp, 4 sw $ra, 0($sp) li $a0, 10 # a=10 li $a1, 15 # b=15 jal multi move $t0, $v0 ... lw $ra, 0($sp) addi $sp, $sp, 4 jr $ra multi: li $v0, 0 # res=0 li $t0, 0 # i=0 ciclo: bge $t0, $a1, fim add $v0, $v0, $a0 addi $t0, $t0, 1 b ciclo fim: jr $ra Apenas um registo é guardado na stack 23-02-2019 Arquitectura de Computadores
Programação em assembly Funções recursivas int factorial (int n) { if (n<=1) return (1); else return (n* factorial(n-1)); } ASSEMBLY factorial: sub $sp, $sp, 8 sw $ra, 4($sp) sw $a0, 0($sp) bgt $a0, 1, else li $v0, 1 b fim else: addi $a0, $a0, -1 jal factorial lw $a0, 0($sp) mult $v0, $a0, $v0 fim: lw $ra, 4($sp) addi $sp, $sp, 8 jr $ra 23-02-2019 Arquitectura de Computadores
Programação em assembly Activation record Se os registos não são suficientes para todas as variáveis ou parâmetros, então estas são guardadas na stack, no activation record Parâmetros Antigo $fp Endereço de retorno Registos Variáveis locais $fp $sp 23-02-2019 Arquitectura de Computadores