2
I’m trying to make a simple program: allocate on the stack an integer, calls scanf
from the C library and print it on the screen. I’ve done the same Disassembly in C, and I try to reimplement it, without success. I have tested the allocation without making any call in C, without any error. The problem is Microsoft’s x64 convention. What’s wrong with the following program?
bits 64
section .data
local1 db 'Hello. Input a number, please.',10,'> ', 0
local2 db '%u', 0
local3 db 10,'You input: %u', 0
section .text
extern printf
extern scanf
extern exit
extern getch
global WinMain
WinMain:
push rbp
mov rbp, rsp
mov dword[rbp - 4], 0
; = push dword 0 em 64 bits
mov rcx, local1
call printf ;imprime o "pedido"
mov rcx, local2
lea rdx, [rbp - 4] ;endereço da variável alocada
call scanf
mov rcx, local3
call printf
call getch
xor rcx, rcx ;coloca o valor de saída como 0
call exit ;sai
mov rsp, rbp
pop rbp ;stack frame de saída
leave
PS.: (Consider | a line break) I’ve tried switching mov dword[rbp - 4], 0
for sub rsp, 4 | mov dword[rsp-4], 0
and push word 0 | push word 0
(push dword
is illegal in 64 bits).
Marcus, that’s exactly what it was: sub rsp, 80. I didn’t know why, and I thought it was the compiler’s thing (there were several compiler-only Abels)
– user2692
Ah, I forgot to say that to balance the stack at the end of the function would need to undo all the steps in the opposite order. In case it would be a
add rsp, 80
, although in this case it should not be mandatory because the program ends before that, already in Exit.– marcus
how do I handle my variable? Should I use rbp - 4 or rbp - 76 ?
– user2692
The parameters should be at the top of the stack (smaller memory addresses) when a call is made. Then the local variables of each function should have larger addresses (Obs.: I’m running out of time to give a more detailed answer, then tell me if you got it)
– marcus
As expected, rbp - 76. The only fact I didn’t understand is: why do I have to allocate a local variable of size 16? I can’t just allocate a 4?
– user2692
Whoa, are you sure it’s rbp - 76? Take a look at the diagrams of these sites: http://eli.thegreenplace.net/2011/09/06/stack-frame-layout-on-x86-64/ and https://msdn.microsoft.com/en-us/magazine/cc300794.aspx (the first speaks of both Linux and Windows, beware of confusing) Local variables are "closer" to rbp (so rbp - 4) and then (then it means "smaller addresses", not shown in the diagrams) comes the location of the parameters (I didn’t answer this yesterday because I was in a hurry and would confuse everything).
– marcus
The stack has to be aligned in 16 bytes. Probably because it allows better performance (ensures that the least significant bits will always be 0). Unless your function does not call any other (ie if your function is a Function Leaf), in which case it can do whatever you want with the stack! Of course you can find another place to store your variable. Remember that: the function that called yours must have allocated 16*4 bytes in rbp + XXXX, and that you are not required to use rbp (you can use rsp for everything), you can allocate these 8 bytes to something else.
– marcus
Let’s go continue this discussion in chat.
– marcus