如何获得碱堆栈指针的地址 [英] How to get address of base stack pointer

查看:165
本文介绍了如何获得碱堆栈指针的地址的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在将应用程序移植从86到64的过程。我使用Visual Studio 2009;大部分的code是C ++,有些部分是纯C.对x64的编译和我们的应用程序中包含内联汇编的几个部分时,__asm​​关键字不支持。我没有写这个code,所以我不知道到底是什么等应该做的事做:

I am in the process of porting an application from x86 to x64. I am using Visual Studio 2009; most of the code is C++ and some portions are plain C. The __asm keyword is not supported when compiling towards x64 and our application contains a few portions of inline assembler. I did not write this code so I don't know exactly what et is supposed to do:

int CallStackSize() {
    DWORD Frame;
    PDWORD pFrame;
    __asm
        {
            mov EAX, EBP
            mov Frame, EAX
        }
    pFrame = (PDWORD)Frame;
    /*... do stuff with pFrame here*/
}

EBP是基本指针当前函数的栈。是否有某种方式来获得,而无需使用内联汇编堆栈指针?我一直在寻找,微软提供了作为内联汇编的替代品的内在,但我无法找到任何东西给我的东西有用。任何想法?

EBP is the base pointer to the stack of the current function. Is there some way to obtain the stack pointer without using inline asm? I have been looking at the intrinsics that Microsoft offers as a substitute for inline asm but I could not find anything that gave me something usefull. Any ideas?

安德烈亚斯问什么东西是用PFRAME完成。下面是完整的功能:

Andreas asked what stuff is done with pFrame. Here is the complete function:

int CallStackSize(DWORD frameEBP = 0)
{
    DWORD pc;
    int tmpint = 0;
    DWORD Frame;
    PDWORD pFrame, pPrevFrame;

    if(!frameEBP) // No frame supplied. Use current.
    {
        __asm
        {
            mov EAX, EBP
            mov Frame, EAX
        }
    }
    else Frame = frameEBP;

    pFrame = (PDWORD)Frame;
    do
    {
        pc = pFrame[1];
        pPrevFrame = pFrame;
        pFrame = (PDWORD)pFrame[0]; // precede to next higher frame on stack

        if ((DWORD)pFrame & 3) // Frame pointer must be aligned on a DWORD boundary. Bail if not so.
        break;

        if (pFrame <= pPrevFrame)
        break;

        // Can two DWORDs be read from the supposed frame address?
        if(IsBadWritePtr(pFrame, sizeof(PVOID)*2))
        break;

        tmpint++;
    } while (true);
    return tmpint;
}

时,不使用可变PC。它看起来像这样功能走下堆栈,直到它失败。它假定它不能读取外部应用程序栈,所以当它失败已测得的调用堆栈的深度。这code并不需要在_EVERY_SINGLE编译器来编译在那里。只是VS2009。应用程序不需要EVERY_SINGLE计算机上运行那里。我们部署的完全控制权,因为我们安装/配置它自己,并提供整个事情给我们的客户。

The variable pc is not used. It looks like this function walks down the stack until it fails. It assumes that it can't read outside the applications stack so when it fails it has measured the depth of the call stack. This code does not need to compile on _EVERY_SINGLE compiler out there. Just VS2009. The application does not need to run on EVERY_SINGLE computer out there. We have complete control of deployment since we install/configure it ourselves and deliver the whole thing to our customers.

推荐答案

做的是重写无论这个函数,这样它不需要访问实际的帧指针真正正确的事情。这肯定是不好的行为。

The really right thing to do would be to rewrite whatever this function does so that it does not require access to the actual frame pointer. That is definitely bad behavior.

但是,做你在找什么,你应该能够做到:

But, to do what you are looking for you should be able to do:

int CallStackSize() {
    __int64 Frame = 0; /* MUST be the very first thing in the function */
    PDWORD pFrame;

    Frame++; /* make sure that Frame doesn't get optimized out */

    pFrame = (PDWORD)(&Frame);
    /*... do stuff with pFrame here*/
}

这部作品的原因是,通常在C函数所做的第一件事就是分配本地变量之前保存过的基指针(EBP)的位置。通过创建一个局部变量(帧),然后得到的,如果地址,我们真的得到这个函数的栈帧的起始地址。

The reason this works is that in C usually the first thing a function does is save off the location of the base pointer (ebp) before allocating local variables. By creating a local variable (Frame) and then getting the address of if, we're really getting the address of the start of this function's stack frame.

请注意:一些优化可能会导致被删除的框架的变量。或许不会,但要小心。

Note: Some optimizations could cause the "Frame" variable to be removed. Probably not, but be careful.

二注意:您原来的code和这也code操纵数据指向PFRAME当PFRAME本身就是在堆栈中。它可以在这里改写PFRAME偶然的,然后你将有一个坏的指针,可以得到一些怪异的行为。要特别留意这一点从86移动到64时,因为PFRAME现在是8个字节,而不是4,所以如果你的老做PFRAME东西code内存搞乱之前占帧和PFRAME的大小,你需要考虑新的,更大的尺寸。

Second Note: Your original code and also this code manipulates the data pointed to by "pFrame" when "pFrame" itself is on the stack. It is possible to overwrite pFrame here by accident and then you would have a bad pointer, and could get some weird behavior. Be especially mindful of this when moving from x86 to x64, because pFrame is now 8 bytes instead of 4, so if your old "do stuff with pFrame" code was accounting for the size of Frame and pFrame before messing with memory, you'll need to account for the new, larger size.

这篇关于如何获得碱堆栈指针的地址的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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