首页 文章

没有推动就从堆栈中弹出

提问于
浏览
3

我目前正在学习高级汇编语言,并且一直在讨论堆栈的概念 . 我想我理解得很好,但在实践中我有一些问题 .

堆栈增长,ESP寄存器始终指向堆栈的顶部 . 低内存中的地址 . 如果有东西被推入堆栈,那么ESP应该递减 .

EBP用作帧指针,据我所知,应该总是超过ESP .

然而,通过以下计划:

stdout.put(esp, nl);
stdout.put(ebp, nl);
push(ike);
stdout.put(esp, nl);
stdout.put(ebp, nl);
push(ike);
stdout.put(esp, nl);
stdout.put(ebp, nl);
pop(eax);
pop(eax);
pop(eax);
pop(eax);
stdout.put(esp, nl);
stdout.put(ebp, nl);

似乎并非如此 . 看输出:

0018FF6C 0018FF70

0018FF68 0018FF70

0018FF64 0018FF70

0018FF74 0018FF70

EBP始终相同,ESP在第一次推送时递减4个字节,然后在第二次推送时递减4个字节 .

在此之后我很困惑 . 在我的前两次弹出后,ESP应该回到它开始的地方 . 如果我没有把任何东西推到堆栈上,怎么能再做两次pop?我弹出什么?

EAX的进一步弹出和打印显示一些数字,然后是0,然后是更多的数字 . 所以,我肯定会弹出一些东西......但是什么?我的程序存储器属于哪个部分,为什么没有受到影响?

为什么EBP根本没有受到影响?

另外,为什么ESP减少了4个字节,而不是8个?

如果有人能帮助我理解这一点,我将非常感激 .

2 回答

  • 1

    EBP不会被推/弹指令修改,它是手动设置的,所以除非你自己更改它,否则它将保持不变 .

    IKE的推送导致4字节的更改,所以显然你在这里处于32位模式 .

    EAX(32位)的4个弹出将导致16字节(10h)的更改,就像它们一样 .

    不知道这里有什么问题 . 似乎按照我的预期工作?

  • 0

    除了你推送和弹出的东西之外,堆栈还用于保存每个函数's stack frame (i.e. local variables), return address, the old ebp (specifically where the current ebp is) and function'的参数 . 所以你弹出的是你的函数的堆栈框架 .
    如果您反汇编程序,您会看到:

    push    param3          ; suppose func takes 3 parameters, they're
    push    param2          ; pushed in reversed order (C-style)
    push    param1
    call    func            ; call pushes also the return address, i.e. the
                            ; address of the instrucion after the call
    
    ...
    
    func:
    push   ebp              ; this is done for preserving the caller's stack frame
    mov    ebp, esp         ; now we set up the beginning of func's stack frame
    sub    esp, smth.       ; and its width, enough to fit all func's variables
    

    此时堆栈将是这样的:

    00000058:    arg3
            00000054:    arg2
            00000050:    arg1
            0000004c:    return address
     ebp -> 00000048:    caller's ebp
            ...          ...               -
            00000034:    random stuff       |  func's stack frame, random because they
            00000030:    random stuff       |  are uninitialized
     esp -> 0000002c:    random stuff      -
    

    最后,您只需按下并弹出4个字节,因为这是您机器的字大小,这样您就可以保存整个寄存器 . 一枪

相关问题