Segmentation fault in assembler language

I'm learning assembler language. When I started reading about stack, I tried to write code that adds two numbers and debug it. But when try to call function "add" I get

Program received signal SIGSEGV, Segmentation fault.

The main problem is that the program gives this error without even entering the ADD function. That is, the program, even without executing the call add command, terminates urgently.

here is the code:

global _start

section .text
_start:

call main

add:
        push ebp
        mov ebp, esp
        sub esp, 4

        mov eax, [ebp + 8]
        mov ebx, [ebp + 12]
        add eax, ebx
        mov [ebp - 4], eax
        ret

main:
        push ebp
        mov ebp, esp
        sub esp, 12

        mov [ebp - 8], dword 2
        mov [ebp - 12], dword 40

        call add

        ret

here is the debugging process


Firstly, you never exit the program, which would cause the program to go to an infinite loop, if it could return from the functions successfully. You see, ret is equivalent to pop eip, which jumps into the address at the top of the stack and continues execution there. Your program however, pushed many additional values onto the stack without ever restoring it, thus, when the ret instruction was executed, the wrong address was popped. You really need to be careful when it comes to the stack in procedures.

I fixed the errors and mentioned, and maybe you could pick up some ideas from my version. But in any case, just remember to restore the stack and exit from the program.


global _start

section .text
_start:

call main
mov ebx, eax   ;; using the sum as the return code
mov eax, 1     ;; SYS_exit
int 0x80       ;; syscall

add:
        push ebp          ;; stack frame
        mov ebp, esp 

        mov eax, [esp+8]  ;; first argument (getting esp+8 because we pushed ebp)
        mov ebx, [esp+12] ;; second argument
    
        add eax, ebx 

        mov esp, ebp 
        pop ebp           ;; stack frame restore
        ret               ;; returning from function

main:
        push ebp 
        mov ebp, esp      ;; set up frame pointer.

        push dword 2      ;; pushing the arguments
        push dword 40

        call add 
    
        mov esp, ebp      ;; tear down stack frame
        pop ebp           ;; restore frame pointer
        ret             ;; returning to _start where we exit
nasm -g -f elf32 -o program.o program.asm ; ld -g -m elf_i386 -o program program.o ; ./program ; echo $?