Every function must have its own stack frame, this is part of the function convention. So since main
is a function, you should start the stack frame with push ebp
and mov ebp, esp
and end with leave
. The reason you have to do this with main
is because it not is the main function of your executable. In fact there will be another, provided by the compiler, which will call main
. In Windows it would be WinMain
whereas in Linux it would be _start
. So the code needs to look like this:
global main
extern printf
section .data
helloworld db 'Hello World',0
section .text
main:
push ebp
mov ebp, esp
push helloworld
call printf
leave ; Equivalente a "pop ebp"
mov eax, 0 ; Retorne 0
ret
But you are also interested in using x64 code. It will not work that way. The convention for passing arguments in x86 numerics (or pointers as is the case) is to add them in the stack. But in the case of x64 the convention changes to use the following registers for the first 6 parameters: rdi
, rsi
, rdx
, rcx
, r8
and r9
. From the seventh onwards, you'll need to stack as usual. So the code looks like this:
global main
extern printf
section .data
helloworld db 'Hello World',0
section .text
main:
push rbp
mov rbp, rsp
mov rdi, helloworld
call printf
leave
mov rax, 0 ; Retorne 0
ret
Note, however, that different systems or different architectures may change these conventions. You will always need to choose exactly what your target system is and search its conventions.