Aprenda Assembly

  • Página Inicial
  • Contato!
  • Tudo sobre Assembly Parte 1!
  • Tudo sobre Assembly Parte 2!
  • Tudo sobre Assembly Parte 3!
  • Tudo sobre Assembly Parte 4!
  • Tudo sobre Assembly Parte 2

    Funções de Conversão (32 bits)

    Coloque essas funções abaixo do mostra_valor:

    
    ; Converte string para inteiro:
    ; Entrada esi (ponteiro da string), ecx (número de caracteres da string)
    string_to_int:
        xor ebx, ebx
    
    .prox_digito:
        movzx eax, byte [esi] ; Em 64 bits use rsi
        inc esi
        sub al, '0'
        imul ebx, 10
        add ebx, eax ; ebx = ebx * 10 + eax
        loop .prox_digito
        mov eax, ebx
    
        ret
    
    ; Converter inteiro para string:
    ; Entrada eax (inteiro pra converter) e esi (ponteiro da string)
    ; Saída eax
    
    int_to_string:
        add esi, 9
        mov byte [esi], 0
        mov ebx, 10
        
    .prox_digito:
        xor edx, edx
        div ebx
        add dl, '0'
        dec esi
        mov [esi], dl
        test eax, eax
        jnz .prox_digito ; Pule até ser zero
        mov eax, esi
    
        ret
    
    

    Altere as sections e o start assim:

    
    section .data
        v1 dw '105', 0xa ; 5 no formato variável
    
    section .bss ; Na .bss colocamos todas as variáveis que quisermos
        buffer: resb 10 ; Máximo de caracteres permitidos
    
    section .text
        global _start
    
    _start:
        call converter_valor
        call mostrar_valor
    
    

    Altere as funções criadas anteriormente também:

    
    converter_valor:
        lea esi, [v1]
        mov ecx, 3
        call string_to_int
        add eax, 1  
    
        ret
    
    mostrar_valor:
        lea esi, [buffer]
        call int_to_string
        mov eax, 4
        mov ebx, 1
        mov ecx, buffer
        mov edx, 10
    
        int 0x80
    
        ret
    
    

    Dessa forma, na session .data podemos passar números com até 10 caracteres:

    
    section .data
        v1 dw '105', 0xa ;
    
    

    Menu do Sistema (32 bits)

    Faça o seguinte programa:

    
    section .data ; Variáveis fixas
        ; Tit é o tipo da variável
        tit         db 10, "+-------------+", 10, "| Calculadora |", 10, "|             |", 10, "+-------------+", 0
        ltit        equ $- tit
    
        obVal1      db 10, "Valor 1: ", 0
        lobVal1     equ $- obVal1
    
        obVal2      db 10, "Valor 2: ", 0
        lobVal2     equ $- obVal2
    
        opc1        db 10, "1, Adicionar", 0
        lopc1       equ $- opc1
    
        opc2        db 10, "2, Subtrair", 0
        lopc2       equ $- opc2
    
        opc3        db 10, "3, Muliplicar", 0
        lopc3       equ $- opc3
    
        opc4        db 10, "4, Dividir", 0
        lopc4       equ $- opc4
    
        msgOpc      db 10, "Deseja realizar? ", 0
        lmsgOpc     equ $- msgOpc
    
        msgErro     db 10, "Valor da Opção Inválida!", 0
        lmsgErro    equ $- msgErro
    
        salLinha    db 10, 0
        lsalLinha   db $- salLinha
    
    section .bss ; Variável que podem mudar de valor
        opc     resb 2
        num1    resb 10
        num2    resb 10
        result  resb 10
    
    section .text
        global _start
    
    _start:
        mov ecx, tit
        mov edx, ltit
        call mst_saida
    
        ; Valor 1
    
        mov ecx, obVal1
        mov edx, lobVal1    
        call mst_saida
    
        mov ecx, num1
        mov edx, 10
        mov eax, 3
        mov ebx, 0
    
        int 80h
    
        ; Valor 2
    
        mov ecx, obVal2
        mov edx, lobVal2    
        call mst_saida
    
        mov ecx, num2
        mov edx, 10
        mov eax, 3
        mov ebx, 0
    
        int 80h
    
        ; Opção 1
    
        mov ecx, opc1
        mov edx, lopc1      
        call mst_saida
    
        ; Opção 2
    
        mov ecx, opc2
        mov edx, lopc2      
        call mst_saida
    
        ; Opção 3
    
        mov ecx, opc3
        mov edx, lopc3      
        call mst_saida
    
        ; Opção 4
    
        mov ecx, opc4
        mov edx, lopc4      
        call mst_saida
        
        ; Ler opções:
    
        mov ecx, msgOpc 
        mov edx, lmsgOpc        
        call mst_saida
    
        mov ecx, opc
        mov edx, 2
        mov eax, 3
        mov ebx, 0
    
        int 80h
    
        ; Conversões para decimal
    
        mov ah, [opc]
        sub ah, '0'
    
        ; Verifica opções:
    
        cmp ah, 1
        je  adicionar
    
        cmp ah, 2
        je  subtrair
    
        cmp ah, 3
        je  multiplicar
    
        cmp ah, 4
        je  dividir
        
        mov ecx, msgErro
        mov edx, lmsgErro
        call mst_saida
        jmp exit
    
    ; Métodos
    adicionar:
        jmp exit
    
    subtrair:
        jmp exit
    
    multiplicar:
        jmp exit
    
    dividir:
        jmp exit
    
    mst_saida:
        mov eax, 4
        mov ebx, 0
    
        int 80h
    
        ret
    
    exit:
        mov ecx, salLinha
        mov edx, lsalLinha  
        call mst_saida
    
        mov eax, 1
        mov ebx, 0
    
        int 80h
    
    

    Agora complete as funções de adicionar, subtrair, multiplicar e dividir, assim:

    
    adicionar:
        add eax, ebx
    
        jmp exit
    
    subtrair:
        sub eax, ebx
    
        jmp exit
        
    multiplicar:
        mov ebx, eax
        mul ebx
    
        jmp exit
    
    dividir:
        mov ebx, eax
        div ebx
    
        jmp exit
    
    

    União com o C++ (32 bits)

    Crie um arquivo cpp (como troca.cpp) para colocarmos nosso programa em C++, com esse código:

    
    #include <iostream>
    
    using namespace std;
    
    extern "C" int getValorASM(int a); // Isso receberá o valor do Aseembly
    
    int main() {
        cout << "ASM me DEU " << getValorASM(32) << endl;
        
        return 0;
    }
    
    

    Faça também esse programa em Assembly:

    
    global getValorASM ; Mesmo nome no arquivo cpp
    
    segment .text
    
    getValorASM:
        mov eax, edi ; Pega o valor que receberá do cpp, use rdi com 64 bits
        add eax, 1
    
        ret
    
    

    Compile o programa Assembly com o comando nasm, e depois monte o C++ com esse código objeto do Assembly, digitando g++ troca.o troca.cpp -o troca -no-pie -m32.

    Ele deverá retornar 33, que é a soma do 1 do Assembly com o 32 do C++.

    Crie um arquivo com o nome makefile, sem extensão, desse jeito mesmo, e coloque esse código (não esqueça da tabulação):

    
    troca: troca.cpp troca.o
        g++ troca.o troca.cpp -o troca -no-pie -m32
    
    troca.o: troca.asm
        nasm -f elf32 troca.asm -o troca.o
    
    clean:
        rm -f *.o
    
    

    Dessa forma, compilamos o programa apenas digitando make no terminal.

    Saltos Condicionais (32 bits)

    Crie esse programa em C++ primeiramente, com o nome questao.cpp:

    
    #include <iostream>
    
    using namespace std;
    
    extern "C" int question(int a);
    
    int main() {
        if(question(26) == 1) {
            cout << "Número Par!" << endl;
        }
        else {
            cout << "Número Ímpar!" << endl;
        }
    
        return 0;
    }
    
    

    Crie também o questao.asm em Assembly:

    
    global question
    
    segment .text
    
    ; Par é qualquer número que subtrair 2 sucessivamente será igual a zero
    ; Se for menor que zero, ele é ímpar
    
    question:
        mov ebx, edi ; Por onde recebemos o valor
        jmp _testar  ; Pula até o ponto da função testar
    
    _testar:
        cmp ebx, 0   ; Compara o valor de ebx com zero
        je _par      ; Igual a zero
        jl _impar    ; Menor que zero
        sub ebx, 2
        jmp _testar
    
    _par:
        mov eax, 1
        ret
    
    _impar:
        mov eax, 0
        ret
    
    

    E o makefile com esse código:

    
    questao: questao.cpp questao.o
        g++ questao.o questao.cpp -o questao -no-pie -m32
    
    questao.o: questao.asm
        nasm -f elf32 questao.asm -o questao.o
    
    clean:
        rm -f *.o
    
    

    Mude o número 26 para 27 no arquivo cpp e compile de novo, para ver o resultado diferente.