;; Arvorezinha 2.0; x86 Assembly; Copyright (C) 2010 Pedro de Oliveira; http://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 VariaveisSECTION .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 .textmain: 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 alturaciclo_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 0ciclo_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 ASTERISCOSprepara_asteriscos: mov dword [x], 1 ; Mete x a 1ciclo_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 ARVOREprepara_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 1ciclo_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 0c_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 0c_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 0c_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 0c_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 TRONCOjafoste: 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 0x80print: mov ecx,[esp+4] ; Mete o argumento em ECX mov edx,1 ; Length mov ebx,1 ; stdout mov eax,4 ; sys_write int 0x80 retincrementa_x: mov eax, [x] inc eax mov dword [x], eax retincrementa_i: mov eax, [i] inc eax mov dword [i], eax ret