Every function must have its own stack frame, this is part of the function convention. So, how main
is a function, you must start the stack frame with push ebp
and mov ebp, esp
and end with leave
. The reason you have to do this with main
it’s because she nay is the main function of your executable. Actually there will be another, provided by the compiler, which will call main
. In Windows would be WinMain
while on Linux is the _start
. So the code needs to be 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 code in x64. This way it won’t work. The convention for passing arguments in numerical x86 (or pointers as is the case) is to add them to 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 will 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
It is worth noting, however, that different systems or different architectures can change these conventions. You will always need to choose exactly what your target system is and search its conventions.
In this link there is a example for Windows 64 bit environment.
– lsalamon