Reputation: 11045
I still get lost with the stack related operations often and in this case the problem is the RET instruction, which pops a wrong address for the eip register. I use NASM and my code looks like this:
start:
call GiveMeAHandler
call GetCommandLine
ret
GiveMeAHandler:
push ebp
mov ebp, esp
push edi
push esi
push dword -11
call dword [F_GetStdHandle] ; It executes correctly and returns
mov [StdHandler], eax ; StdHandler is stored in BSS
add esp, 4
pop esi
pop edi
pop ebp
ret ; This returns to some weird address
GetCommandLine:
; ...
; I don't get here because the function above wrong return
Maybe I have exaggerated a little with the ebp, edi, esi
pushing and popping (they are not altered after all) but even if I remove them the ret
instruction still returns a wrong address (77AE7094) instead of 0040100A, where I call the second function.
Upvotes: 1
Views: 270
Reputation: 11706
By default, Windows uses the stdcall
calling convention, where function arguments are pushed onto the stack (right to left), and the callee cleans up the stack. In other words, when GetStdHandle
returns, the stack will already be restored to before your push dword -11
instruction. Try removing the add esp, 4
line and see if that fixes it.
Upvotes: 2
Reputation: 58427
Let's look at what NASM generates for push dword -11
:
6AF5 push byte -0xb
So NASM took your dword
and replaced it with a byte
(which will be promoted to a word
by the CPU, since a word
is the smallest unit you can push
onto the stack).
Why did it do that? Well, there's an optimizer which is enabled by default, and which will attempt to optimize the size of immediates.
Since you (understandably) thought you had pushed a dword
and later add 4 to esp
you end up with an unbalanced stack.
To stop this from happening you can either add a strict
specifier, as in:
push strict dword -11
Or use the -O0
option when assembling.
Upvotes: -1