Mais um blog inútil.

Dezembro 14, 2010

Árvorezinha 2.0

Filed under: Arvorezinha,Assembly,Coding,Drama,Useless — falso @ 1:07

Ora viva amigos!

Há uns tempos no trabalho um colega meu começou a fazer pouco das minhas árvorezinhas, a dizer que só eram meia árvore, e que eu devia era de fazer uma árvore completa. Eu fiquei SENTIDO com tal AFRONTA, e fiquei a MATUTAR sobre isso, até que decidi por mãos à obra, e criar a Árvorezinha 2.0.

Primeiro decidi faze-la em C porque é a linguagem STANDARD!

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
        int altura;
        int i,x;
        int lul;

        if (argc < 2)
        {
                return(0);
        }
        altura = atoi(argv[1]);

        /* Ciclo da altura da Arvore */
        for(i = 1; i <= altura; i++)
        {

                /*
                        Numero de Espaços
                        Começa em 0 porque existem linhas com 0 espaços
                        Algoritmo: altura - linha
                */
                for(x = 0 ; x < (altura-i); x++)
                {
                        putchar(' ');
                }

                /*
                        Numero de Asteriscos
                        Começa em 1 porque não existem linhas sem *
                        Algoritmo: (2 * linha) - 1
                */
                for (x = 1; x <= (2*i)-1; x++)
                {
                        putchar('*');
                }

                putchar('\n');
        }

        /* Largura ultima linha */
        lul = (altura * 2) - 1;

        /*
                Ciclo da altura do tronco
                Algoritmo: altura / 2
        */
        for(i = 1; i <= (altura/2); i++)
        {
                /*
                        Por causa do ASCII nao permitir meio char
                        tive de fazer duas implementacoes diferentes,
                        uma para quando o  valor da altura do tronco
                        e' par, e outra para quando e' impar.
                */
                if (altura % 2)
                {
                        /* Impar */

                        /*
                                Numero de Espaços
                                Algoritmo: (lul / 4) - 1
                        */
                        for(x = 0; x <= (lul/4)-1; x++)
                        {
                                putchar(' ');
                        }


                        /*
                                Numero de # (tronco)
                                Algoritmo: lul / 2
                        */
                        for(x = 0; x <= (lul/2); x++)
                        {
                                putchar('#');
                        }

                        putchar('\n');
                }
                else
                {
                        /* Par */

                        /*
                                Numero de Espaços
                                Algoritmo: lul / 4
                        */
                        for(x = 0; x <= (lul/4); x++)
                        {
                                putchar(' ');
                        }


                        /*
                                Numero de # (tronco)
                                Algoritmo: (lul / 2) - 1
                        */
                        for(x = 0; x <= (lul/2)-1; x++)
                        {
                                putchar('#');
                        }

                        putchar('\n');
                }
        }

}

A pedido de muitas famílias, foi me imposta a tarefa de fazer um RFC da nova árvorezinha, mas não tenho muito jeito para escrever algoritmos em pseudo-código. Então tal obra heróica fica para o caro leitor, façam me um baseado no código em C e enviem-me!

Segundo as próprias leis já pré-estabelecidas da Árvorezinha, tem de existir uma implementação em Assembly! Então não podia cá faltar a minha versão em x86 Assembly.


;
; Arvorezinha 2.0
; x86 Assembly
; Copyright (C) 2010 Pedro de Oliveira
; //blol.org
;
; this assembly can never fail
;
        BITS            32
        GLOBAL          main

; Vou usar duas funcoes da libc para o codigo nao crescer gigantescamente
; com rotinas que nao interessam nada para aqui.
        EXTERN          atoi
        EXTERN          printf

; Definicao das Variaveis
SECTION         .data

        argc    dd      0
        argv    dd      0

        erro    db      "ERRO! Executar: %s <altura da arvore>",10,0

        card    db      '#'
        newl    db      0xa
        aste    db      '*'
        espa    db      ' '

        altura  dd      0
        i       dd      1
        x       dd      0
        lul     dd      0

; He cometh!
SECTION         .text

main:
        pop     eax                     ; Ignorar...

        pop     eax                     ; Saca o argc da Stack
        mov     dword [argc], eax       ; Guarda o valor na variavel argc

        pop     ebx                     ; Saca a posicao de memoria do
                                        ; argv[0] da Stack
        mov     eax, dword [ebx]        ; Mete a posicao em EAX
        mov     [argv], eax             ; Guarda-a em argv

        add     ebx,0x4                 ; Salta 4 bytes para a frente
                                        ; para o argv[1] ficar em EBX

        mov     eax, [argc]             ; Mete o argc em EAX
        cmp     eax, 0x2                ; Verifica se e' diferente de 2
        jne     jafoste                 ; Se for sai com erro

        push    dword [ebx]             ; Mete o valor de argv[1] na Stack
        call    atoi                    ; Corre o atoi com esse valor
        mov     [altura], eax           ; O resultado fica em EAX, guarda
                                        ; na variavel altura

ciclo_linhas:
        ; INICIO - CICLO DAS LINHAS DA ARVORE
        mov     eax, [i]                ; i em EAX
        mov     ebx, [altura]           ; altura em EBX

        cmp     ebx, eax                ; Compara
        jb      prepara_tronco          ; i > altura ? proximo passo
        mov     dword [x], 0            ; Mete x a 0

ciclo_espacos:
        ; INICIO - CICLO DE ESPAÇOS ANTES DOS ASTERISCOS
        mov     eax, [x]                ; x em EAX

        ; pretende-se (altura - i) em EBX
        mov     ebx, [altura]           ; altura em EBX
        mov     ecx, [i]                ; i em ECX
        sub     ebx, ecx                ; EBX - ECX

        cmp     ebx, eax                ; Compara
        jbe     prepara_asteriscos      ; x >= (altura - i) ? proximo passo

        push    espa                    ; Espaço
        call    print                   ; write()

        call    incrementa_x
        jmp     ciclo_espacos           ; Volta para o inicio do ciclo
        ; FIM - CICLO DE ESPAÇOS ANTES DOS ASTERISCOS

prepara_asteriscos:
        mov     dword [x], 1            ; Mete x a 1

ciclo_asteriscos:
        ; INICIO - CICLO DE ASTERISCOS (ARVORE)
        mov     ebx, [x]                ; x em EBX

        ; pretende-se (2 * i) - 1 em EAX
        mov     eax, 2                  ; 2 em EAX
        mov     ecx, [i]                ; i em ECX
        mul     ecx                     ; Multiplica EAX por ECX
        dec     eax                     ; Subtrai 1 a EAX

        cmp     eax, ebx                ; Compara
        jb      fim_ciclo_linhas        ; x > (2*i)-1 ? proximo passo

        push    aste                    ; Asterisco
        call    print                   ; write()

        call    incrementa_x
        jmp     ciclo_asteriscos        ; Volta para o inicio do ciclo
        ; FIM - CICLO DE ASTERISCOS (ARVORE)

fim_ciclo_linhas:
        push    newl                    ; Newline
        call    print                   ; write()

        call    incrementa_i
        jmp     ciclo_linhas            ; Volta para o inicio
        ; FIM - CICLO DAS LINHAS DA ARVORE

prepara_tronco:
        ; pretende-se (altura * 2) - 1 em EAX
        mov     eax, [altura]           ; altura em EAX
        mov     ecx, 2                  ; 2 em ECX
        mul     ecx                     ; Multiplica EAX por ECX
        dec     eax                     ; Subtrai 1 a EAX
        mov     dword [lul], eax        ; Guarda a largura da ultima linha
                                        ; em lul


        mov     dword [i], 1            ; Mete o i a 1

ciclo_linhas_tronco:
        ; BEGIN - CICLO DAS LINHAS DO TRONCO
        mov     ecx, [i]                ; i em ECX

        ; pretende-se (altura / 2)
        mov     eax, [altura]           ; altura em EAX
        shr     eax, 1                  ; divide por 2

        cmp     ecx, eax                ; Compara ECX com EAX
        jg      sair                    ; i > (altura / 2) ? Adeus!

        mov     eax, [altura]           ; altura em EAX
        test    eax, 1
        je      pc_tronco_par_espacos   ; e' par?

; --------------------------- IMPAR -------------------------------
pc_tronco_impar_espacos:
        mov     dword [x], 0            ; Mete-se x a 0

c_tronco_impar_espacos:
        ; INICIO - CICLO DOS ESPAÇOS ANTES DO TRONCO (IMPAR)
        mov     ecx, [x]                ; x em EAX

        ; pretende-se (lul / 4) - 1 em EAX
        mov     eax, [lul]              ; lul em EAX
        shr     eax, 2                  ; Divide por 4
        dec     eax                     ; Subtrai 1

        cmp     eax, ecx                ; Compara
        jb      pc_tronco_impar_cardinal; x > (lul/4)-1 ? Next!

        push    espa                    ; Espaço
        call    print                   ; write()

        call    incrementa_x
        jmp     c_tronco_impar_espacos  ; Volta para o inicio
        ; FIM - CICLO DOS ESPAÇOS ANTES DO TRONCO (IMPAR)

pc_tronco_impar_cardinal:
        mov     dword [x], 0            ; Mete x a 0

c_tronco_impar_cardinal:
        ; INICIO - CICLO DOS CARDINAIS DO TRONCO (IMPAR)
        mov     ecx, [x]                ; x em ECX

        ; pretende-se (lul / 2) em EAX
        mov     eax, [lul]              ; lul em EAX
        shr     eax, 1                  ; Divide por 2

        cmp     eax, ecx                ; Compara
        jb      fim_ciclo_linhas_tronco ; x > (lul/2) ? Next!

        push    card                    ; Cardinal
        call    print                   ; write()

        call    incrementa_x

        jmp     c_tronco_impar_cardinal ; Volta para o inico
        ; FIM - CICLO DOS CARDINAIS DO TRONCO (IMPAR)

; --------------------- FIM IMPAR --------------------------------


; ----------------------------- PAR ------------------------------
pc_tronco_par_espacos:
        mov     dword [x], 0            ; Mete x a 0

c_tronco_par_espacos:
        ; INICIO - CICLO DOS ESPAÇOS ANTES DO TRONCO (PAR)
        mov     ecx, [x]                ; x em ECX

        ; pretende-se (lul / 4) em EAX
        mov     eax, [lul]              ; lul em EAX
        shr     eax, 2                  ; divide por 4

        cmp     eax, ecx                ; Compara
        jb      pc_tronco_par_cardinal  ; x > (lul / 4) ? Next!

        push    espa                    ; Espaço
        call    print                   ; write()

        call    incrementa_x
        jmp     c_tronco_par_espacos    ; Volto para o inico do ciclo
        ; FIM - CICLO DOS ESPAÇOS ANTES DO TRONCO (PAR)

pc_tronco_par_cardinal:
        mov     dword [x], 0            ; Mete x a 0

c_tronco_par_cardinal:
        ; INICIO - CICLO DOS CARDINAIS DO TRONCO (PAR)
        mov     ecx, [x]                ; x em ECX

        ; pretende-se (lul / 2) - 1 em EAX
        mov     eax, [lul]              ; lul em EAX
        shr     eax, 1                  ; Divide por 2
        dec     eax                     ; Subtrai 1

        cmp     eax, ecx                ; Compara
        jb      fim_ciclo_linhas_tronco ; x > (lul / 2) - 1 ? uhuhuh

        push    card                    ; Cardinal
        call    print                   ; write()

        call    incrementa_x

        jmp     c_tronco_par_cardinal   ; Volta para o inicio do ciclo
        ; FIM - CICLO DOS CARDINAIS DO TRONCO (PAR)
; ----------------------- FIM PAR ----------------------------------

fim_ciclo_linhas_tronco:
        push    newl
        call    print

        call    incrementa_i
        jmp     ciclo_linhas_tronco     ; Volta para o inico do ciclo
        ; FIM - CICLO DAS LINHAS DO TRONCO

jafoste:
        mov     eax, [argv]             ; Mete o apontador de argv em EAX
        push    dword eax               ; Mete o endereço de argv na Stack
        push    dword erro              ; Mete o endereço da String na Stack
        call    printf                  ; Escreve no ecra!


sair:
        mov     ebx,0x0                 ; valor de saida
        mov     eax,0x1                 ; sys_exit
        int     0x80

print:
        mov     ecx,[esp+4]             ; Mete o argumento em ECX
        mov     edx,1                   ; Length
        mov     ebx,1                   ; stdout
        mov     eax,4                   ; sys_write
        int     0x80
        ret

incrementa_x:
        mov     eax, [x]
        inc     eax
        mov     dword [x], eax
        ret

incrementa_i:
        mov     eax, [i]
        inc     eax
        mov     dword [i], eax
        ret

E aqui vai a prova dos nove:

falso@lemonparty:~/src/zbr$ make
rm -f arvore2 arvore.o
nasm -f elf arvore.asm -o arvore.o
gcc -g -o arvore2 arvore.o
falso@lemonparty:~/src/zbr$ ./arvore2 4
   *
  ***
 *****
*******
  ###
  ###
falso@lemonparty:~/src/zbr$ ./arvore2 5
    *
   ***
  *****
 *******
*********
  #####
  #####
falso@lemonparty:~/src/zbr$

Espero lançar futuramente um género de Unit Tests, para testar as varias implementações da Arvorezinha 2.0 que possam surgir, para ver se cumprem o standard ou não.

Espero que tenham gostado do post, até à proxima, fiquem bem e joguem muito! Chuuuuuuack!

3 comentários a “Árvorezinha 2.0”

  1. Armorfist diz:

    Mesmo a tempo do natal fALSO. Não te escapa nada. Ta lindo.

  2. mirage diz:

    Parece-me bem, mas já não tenho muita paciência para fazer mais arvorezinhas.

    Para compilar em linux 64bits:
    nasm -f elf arvorezinha2.asm -o arvorezinha2.o
    gcc -m32 -o arvorezinha2 arvorezinha2.o

  3. [...] última submissão, tem havido vasto progresso no estado da arte da Arvorezinha. Foi lançado um novo standard, e tem havido um renovado interesse em criar arvorezinhas cada vez mais obscuras e [...]

Comentar

widgeon
widgeon
widgeon
widgeon