# This routine does the computation (A**2 + B**2) / (C**2).
# Assumption:  the result of the computation fits in 16 bits.
# It expects the result on ax. The
# values C, B, and A com on the stack as input parameters.
# Memory is dynamically allocated for local variables.
# The caller cleans up the stack.
#
# int FUNC (int A, int B, int C)

# os parâmetros vem na pilha com o seguintes deslocamentos em relacao a EBP

A =  	+8
B =   	+10
C = 	+12

# variáveis locais
temp1	=	-6
temp2	=	-8
temp3	= 	-10

.text     

_FUNC:
        push    %ebp                #initialize reference point to
        mov     %esp, %ebp          #this stack frame

        push    %edx                # salva os registradores usados nesta funcao

        sub     $6, %esp            # abre espaço para variáveis locais

        mov     A(%ebp), %ax        # mov A into AX  # na sintaxe da Intel seria mov AX, [EBP+A]
        imulw   A(%ebp)             # A * A          # note que, para o montador, A é uma constante que vale +4
        mov     %ax, temp1(%ebp)    # store A*A as a local variable

        mov     B(%ebp), %ax        # mov B into AX
        imulw   B(%ebp)             # B * B
        mov     %ax, temp2(%ebp)    # store B*B locally

        mov     C(%ebp), %ax        # C
        imulw   C(%ebp)             # C * C
        mov     %ax, temp3(%ebp)    # store C*C locally

        mov     temp1(%ebp), %ax   # get A*A
        add     temp2(%ebp), %ax   # A*A + B*B
        idivw   temp3(%ebp)        # divide by C*C (answer in AX)

        add     $6, %esp           # libera espaço das variáveis locais

        pop     %edx               # restaura o valor dos registradores
        
#       mov     %ebp, %esp         # em alguns casos isso é usado para limpar a pilha rapidamente
        pop     %ebp

        ret                        # volta ao programa chamador

        .global _start

_start:
        # chama FUNC (10, 20, 5)
        mov   $5, %ax    # empilha C
        push  %ax
        mov   $20, %ax   # empilha B
        push  %ax
        mov   $10, %ax   # empilha A
        push  %ax
        
        call  _FUNC
        
        add   $6, %esp   # libera espaço dos parâmetros
 
        #      devolve o resultado que vem em %ax chamando o núcleo do Linux

        mov    %eax, %ebx      # first syscall argument: exit code
        mov    $1,%eax         # system call number (sys_exit)
        int    $0x80           # call linux kernel


        #      o valor pode ser observado no bash com echo $? 