Program crashes after stack allocation and call in C


I'm trying to make a simple program: it allocates an integer in the stack, calls% c_of% of the C library, and prints it to the screen. I have already disassembled it in C , and I try to reimplement it, without success. I tested the allocation without making any C call without any error. The problem is the Microsoft x64 convention. What is 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
    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

PS: (Consider | a line break) I have already tried to change scanf by mov dword[rbp - 4], 0 and sub rsp, 4 | mov dword[rsp-4], 0 ( push word 0 | push word 0 is illegal in 64 bits).

asked by anonymous 08.02.2015 / 23:07

1 answer


Have you compared the code generated by the compiler to the code you wrote? If you paste the generated assembly here, it might help.

Anyway before calling a function you must allocate space on the stack for 4 parameters , those that are passed in rcx, rdx, r8, r9, even though there are fewer parameters.

So the called function will have space to "spill" on the stack past values and use these registers for other things (to call other functions, get pointers to those parameters, etc.)

I saw that you only spoke in sub rsp, 4 , which advances the stack by 4 bytes (for your integer, and nothing for the parameters), which is insufficient. In addition, the stack must be aligned in 16 bytes between function calls. Remembering that call does push 8 bytes, then each function should fit the stack with 16n +8 bytes to restore alignment , being n the number of 64-bit variables you want.

So I suggest starting the function with sub rsp, 88 (16 * 5 + 8, thus leaving space for 5 values, 4 for calls and 1 for your local variable) and forget all the rest of the stack manipulation henceforth).

If you are pushing rbp, it should serve as the + 8 of the above formula, so you would only need sub rsp, 80 .

Note: untested code snippets.

10.02.2015 / 14:10