Mais um blog inútil.

Abril 5, 2009

Arvorezinha – MIPS Assembly Optimizada

Filed under: Arvorezinha,Assembly — falso @ 17:09

Ola de novo. Com ajuda do sir dongs, optimizei a arvorezinha em mips, e decidi vir blogar sobre isso.
As alterações foram as seguintes:

De:

slt t0,s2,s1 # se s1 < s2 entao t0 = 1
li t1,1 # t1 = 1 para a comparacao do branch seguinte
beq t0,t1,_estrela # se o r0 = 1 (t1) -> _estrela
Para:

>slt t0,s2,s1 # se s1 < s2 entao t0 = 1
bne t0, zero,_estrela # se o r0 ! 0 -> _estrela
Em vez de se verificar quando t1 é 1, compara-se t1 com o registo zero (que tem sempre o valor 0) quando não é igual a 0 é 1 entao, faz se o branch.
De:

>li t1,1 # para a soma seguinte
add t0,s1,t1 # t0 = s1 (counter1) + t1 (1)
move s1,t0 # s1 = t0, actualiza counter1
Para:

addi s1, s1, 1
O dongs aqui novamente, deu me a conhecer a magia da instrução addi.
Depois disto, pensei que podia fazer uma função com o syscall do write, para não repetir duas vezes o código. Então fui descobrir como era um call, mas pelos vistos tal coisa não existe, o que há é a instrução jal "jump and link", que faz o jump para o sitio devido, e mete o endereço para onde se deve voltar no registo $31 (ra), e para voltar basta um jr ra "jump register".
Então adicionei o seguinte código:

.ent _print
_print:
        li a0, 1 # stdout
        li a2,1 # terceiro argumento - numero de bytes a escrever
        li v0,0x000003EC
        syscall
        jr ra
.end _print

E substitui:

De:

li a0,1 # primeiro argumento pro write() - 1 = stdout
la a1,newline # segundo argumento pro write() - endereco da str
li a2,1 # terceiro argumento - numero de bytes a escrever
li v0,0x000003EC
syscall
Para:

la a1,newline # segundo argumento pro write() - endereco da str
jal _print

Até aqui tudo bem, corria, mas à saída dava segmentation fault. O problema é que ao inicio o registo ra tem o return address do que o que lhe executou. E ao executar a instrução jal, o ra é alterado, e depois à saida do programa quando se faz jr ra, o gajo já nao vai para onde era suposto e chora. Então adicionei logo no inicio do programa um move s8,ra que guarda o valor de ra no registo s8, e depois no final antes de sair faço o contrario move ra,s8 e assim o programa já sai sem drama.

O código completo:

#include <regdef.h>

        .data
estrela: .asciiz "*"
newline: .byte 0xa

        .text
        .globl main

.ent main
main:
        la s0,5 # numero total estrelas
        la s1,0 # s1 = 0 - counter1
        move s8,ra # guarda o valor do return adress em s8
.end main

.ent _ciclo1
_ciclo1:
        beq s1,s0,_fim # se s1 = s0 -> _fim
        la s2,0 # s2 = 0 - counter2
.end _ciclo1

.ent _ciclo2
_ciclo2:
        beq s1,s2,_estrela # se s1 = s2 -> estrela
        slt t0,s2,s1 # se s1 &lt; s2 entao t0 = 1
        bne t0, zero,_estrela # se o r0 ! 0 -> _estrela

        la a1,newline # segundo argumento pro write() - endereco da str
        jal _print

        addi s1, s1, 1
        b _ciclo1 # volta ao _ciclo1
.end _ciclo2

.ent _estrela
_estrela:
        la a1,estrela # segundo argumento pro write() - endereco da str
        jal _print

        addi s2, s2, 1
        b _ciclo2 # volta ao ciclo2
.end _estrela

.ent _print
_print:
        li a0, 1 # stdout
        li a2,1 # terceiro argumento - numero de bytes a escrever
        li v0,0x000003EC
        syscall
        jr ra
.end _print

.ent _fim
_fim:
        move ra,s8 # volta a meter o ra em ra
        jr ra
.end _fim

2 comentários a “Arvorezinha – MIPS Assembly Optimizada”

  1. mirage diz:

    Adoro optimizações assembly, continua!

Comentar

widgeon
widgeon
widgeon
widgeon