到底什么是基指针和堆栈指针?他们指的是什么? [英] What is exactly the base pointer and stack pointer? To what do they point?

查看:22
本文介绍了到底什么是基指针和堆栈指针?他们指的是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用来自维基百科的这个例子,其中 DrawSquare() 调用 DrawLine(),

Using this example coming from wikipedia, in which DrawSquare() calls DrawLine(),

(请注意,此图底部的高地址和顶部的低地址.)

(Note that this diagram has high addresses at the bottom and low addresses at the top.)

谁能解释一下在这种情况下ebpesp 是什么?

Could anyone explain me what ebp and esp are in this context?

据我所知,堆栈指针总是指向堆栈的顶部,而基指针总是指向当前函数的开头?或者什么?

From what I see, I'd say the stack pointer points always to the top of the stack, and the base pointer to the beginning of the the current function? Or what?

我的意思是在 Windows 程序的上下文中

edit: I mean this in the context of windows programs

edit2:eip 也是如何工作的?

edit2: And how does eip work, too?

edit3:我有以下来自 MSVC++ 的代码:

edit3: I have the following code from MSVC++:

var_C= dword ptr -0Ch
var_8= dword ptr -8
var_4= dword ptr -4
hInstance= dword ptr  8
hPrevInstance= dword ptr  0Ch
lpCmdLine= dword ptr  10h
nShowCmd= dword ptr  14h

它们似乎都是双字,因此每个占用 4 个字节.所以我可以看到从 hInstance 到 4 个字节的 var_4 之间存在差距.这些是什么?我假设它是返回地址,如维基百科图片所示?

All of them seem to be dwords, thus taking 4 bytes each. So I can see there is a gap from hInstance to var_4 of 4 bytes. What are they? I assume it is the return address, as can be seen in wikipedia's picture?

(编者注:从迈克尔的回答中删除了一个长引号,它不属于问题,但编辑了一个后续问题):

(editor's note: removed a long quote from Michael's answer, which doesn't belong in the question, but a followup question was edited in):

这是因为函数调用的流程是:

This is because the flow of the function call is:

* Push parameters (hInstance, etc.)
* Call function, which pushes return address
* Push ebp
* Allocate space for locals

我的问题(最后,我希望!)现在是,从我弹出要调用的函数的参数到序言结束的那一刻到底发生了什么?我想知道在那些时刻 ebp、esp 是如何演变的(我已经了解 prolog 的工作原理,我只想知道在我将参数推送到堆栈上之后和 prolog 之前发生了什么).>

推荐答案

esp 就是你说的,栈顶.

ebp 通常在函数开始时设置为 esp.函数参数和局部变量是通过分别从 ebp 加上和减去一个常数偏移量来访问的.所有 x86 调用约定都将 ebp 定义为跨函数调用保留.ebp 本身实际上指向前一帧的基指针,这使得调试器中的堆栈遍历和查看其他帧局部变量的工作成为可能.

ebp is usually set to esp at the start of the function. Function parameters and local variables are accessed by adding and subtracting, respectively, a constant offset from ebp. All x86 calling conventions define ebp as being preserved across function calls. ebp itself actually points to the previous frame's base pointer, which enables stack walking in a debugger and viewing other frames local variables to work.

大多数函数序言看起来像:

Most function prologs look something like:

push ebp      ; Preserve current frame pointer
mov ebp, esp  ; Create new frame pointer pointing to current stack top
sub esp, 20   ; allocate 20 bytes worth of locals on stack.

然后在函数的后面你可能会有类似的代码(假设两个局部变量都是 4 个字节)

Then later in the function you may have code like (presuming both local variables are 4 bytes)

mov [ebp-4], eax    ; Store eax in first local
mov ebx, [ebp - 8]  ; Load ebx from second local

您可以启用的

FPO 或 帧指针省略优化实际上会消除这种情况,并使用 ebp 作为另一个寄存器并直接从 esp,但这让调试变得有点困难,因为调试器不能再直接访问早期函数调用的堆栈帧.

FPO or frame pointer omission optimization which you can enable will actually eliminate this and use ebp as another register and access locals directly off of esp, but this makes debugging a bit more difficult since the debugger can no longer directly access the stack frames of earlier function calls.

对于您更新的问题,堆栈中缺少的两个条目是:

For your updated question, the missing two entries in the stack are:

var_C = dword ptr -0Ch
var_8 = dword ptr -8
var_4 = dword ptr -4
*savedFramePointer = dword ptr 0*
*return address = dword ptr 4*
hInstance = dword ptr  8h
PrevInstance = dword ptr  0C
hlpCmdLine = dword ptr  10h
nShowCmd = dword ptr  14h

这是因为函数调用的流程是:

This is because the flow of the function call is:

  • 推送参数(hInstance 等)
  • 调用函数,推送返回地址
  • 推送ebp
  • 为当地人分配空间

这篇关于到底什么是基指针和堆栈指针?他们指的是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆