6.栈、栈帧

栈(Stack)的用途广泛,通常用于存储局部变量、传递函数参数、保存函数返回地址等。调试程序时需要不断查看栈内存,所以掌握栈很重要。

栈是FILO(First In Last Out,后进先出)这个都知道。但是在看汇编的时候一定要注意一些对应的相关细节。比如函数调用的时候,反汇编看到的参数进栈顺序是倒着的等。

栈的特征

内存结构如下:

 

一个进程中,栈顶指针(ESP)初始状态指向栈底端。执行PUSH命令将数据压入栈时,栈顶指针就会上移到站顶端。执行POP命令从栈中弹出数据时,若栈为空,则指针重新移动到栈底端。栈时一种由高地址向低地址扩展的数据结构,是由下往上扩展的(逆向扩展)。

所以 向栈压入数据时,栈顶指针减小,向低地址移动;从栈中弹出数据时,栈顶指针增加,向高地址移动。初始的时候栈顶指针指向占地。

 

栈帧(Stack Frame) 栈帧在程序中用于声明局部变量、调用函数。

栈帧就是利用EBP(栈帧指针,请注意不是ESP)寄存器访问栈内局部变量、参数、函数返回地址等的手段。ESP寄存器承担着栈顶指针的作用,而EBP寄存器则负责形式栈帧指针的职能。程序运行中,ESP寄存器的值随时变化,访问栈中函数的局部变量、参数时,若依ESP值为基准编写程序会十分困难,并且也很难使CPU引用到准确的地址。所以,调用某函数时,先要把用作基准点(函数起始地址)的ESP值保存到EBP,并维持在函数内部。这样,无论ESP的值如何变化,以EBP的值为基准(base)能够安全访问到相关函数的局部变量、参数、返回地址,这就是EBP寄存器作为栈帧指针的作用。

 

提示:某些优化选项可能会优化掉栈帧。


源代码vs2015 C++

#include "stdafx.h"

#include <iostream>

#include <windows.h>

using namespace std;



long add(long a, long b) {

long x = a, y = b;

return (x + y);

}



int main(){

long lNumbera = 1;

long lNumberb = 2;

printf("%d
" ,add(lNumbera , lNumberb));

    return 0;

}

编译运行(Debug)之后OD加载上,找到add函数,看下栈帧操作。

 

原文地址:https://www.cnblogs.com/csnd/p/12061882.html