简体   繁体   English

CALL和RET无法正常工作

[英]CALL and RET don't work as expected

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. 我仍然经常迷失与堆栈相关的操作,在这种情况下,问题是RET指令,该指令为eip寄存器弹出错误的地址。 I use NASM and my code looks like this: 我使用NASM ,我的代码如下所示:

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. 也许我对ebp, edi, esi推送和弹出操作有些夸张了(毕竟它们并没有改变),但是即使我删除了它们, ret指令仍然返回错误的地址( 77AE7094 )而不是0040100A ,我将其称为第二个功能。

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. 默认情况下,Windows使用stdcall调用约定,其中函数参数被压入堆栈(从右到左), 被调用方清理堆栈。 In other words, when GetStdHandle returns, the stack will already be restored to before your push dword -11 instruction. 换句话说,当GetStdHandle返回时,堆栈将已经还原到push dword -11指令之前。 Try removing the add esp, 4 line and see if that fixes it. 尝试删除add esp, 4行,看看是否可以解决。

Let's look at what NASM generates for push dword -11 : 让我们看看NASM为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). 因此,NASM拿起了您的dword ,并用一个byte替换了它(由于一个word是您可以push堆栈的最小单位,因此它将由CPU提升为一个word )。
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. 因为您(可以理解)以为您输入了dword ,后来又添加了4来使您最终esp了不平衡的堆栈。

To stop this from happening you can either add a strict specifier, as in: 要阻止这种情况的发生,您可以添加一个strict说明符,如下所示:

push strict dword -11

Or use the -O0 option when assembling. 或在组装时使用-O0选项。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM