C windbg windows堆栈中的RBP寄存器值

C windbg windows堆栈中的RBP寄存器值,c,windows,assembly,windbg,stack-unwinding,C,Windows,Assembly,Windbg,Stack Unwinding,如果我有像main()-->a()-->b()-->c()这样的代码流,如果我在c()处插入调试器(windbg),并将调试器中所有帧的寄存器值转储为“.frame/r frame\u number”…我是否看到每个帧的RBP的正确值?从文档中,我看到RBP是一个非易失性寄存器,并在函数调用期间保存……这是否意味着我们只有在展开时才能获得正确的RBP值?……如果我在调试器中停止并以上述方式转储,如果是,调试器如何显示所有帧的变量值如果我们单击该帧您可能还需要使用/c覆盖本地上下文,否则如果您打算

如果我有像main()-->a()-->b()-->c()这样的代码流,如果我在c()处插入调试器(windbg),并将调试器中所有帧的寄存器值转储为“.frame/r frame\u number”…我是否看到每个帧的RBP的正确值?从文档中,我看到RBP是一个非易失性寄存器,并在函数调用期间保存……这是否意味着我们只有在展开时才能获得正确的RBP值?……如果我在调试器中停止并以上述方式转储,如果是,调试器如何显示所有帧的变量值如果我们单击该帧

您可能还需要使用/c覆盖本地上下文,否则如果您打算将其用于某些目的,将为所有帧显示帧0的baseptr

:\>ls -lg & cat stackbase.cpp
total 4
-rw-rw-rw-  1 0 354 2020-11-24 19:46 stackbase.cpp


#include <stdio.h>
#include <stdlib.h>
int c (int c) {
    return c+9;     //16
}
int b (int b) {
    return b+c(7);  //21
}
int a (int a) {
    return a+b(5);  //argv[1]==0=>21
}
int main ( int argc , char* argv[] ) {
    int ans = 0;
    if(argc == 2) {
        ans = a(atoi(argv[1]));
    }
    printf("%d\n", ans);
    return ans;
}


:\>cl /Zi /W4 /analyze /Od /EHsc /nologo stackbase.cpp /link /release
stackbase.cpp

:\>stackbase.exe  1316
1337
您可以使用这两个命令检查差异

0:000> !for_each_frame ".frame /r @$frame; r ebp"
0:000> !for_each_frame ".frame /r /c @$frame; r ebp"
这是just/r的结果,它将始终打印最后一组baseptr 而在这个32位的演示中,ebp在所有其他帧中都是不同的

0:000> !for_each_frame ".frame /r @$frame; r ebp"
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
00 0026f954 011a101a stackbase!c
00 0026f954 011a101a stackbase!c
eax=00000524 ebx=7ffd7000 ecx=00000524 edx=00000000 esi=011ea760 edi=003c9128
eip=011a1000 esp=0026f958 ebp=0026f954 
stackbase!c:
011a1000 55              push    ebp
ebp=0026f960
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
01 0026f960 011a103a stackbase!b+0xa
01 0026f960 011a103a stackbase!b+0xa
eax=00000524 ebx=7ffd7000 ecx=00000524 edx=00000000 esi=011ea760 edi=003c9128
eip=011a101a esp=0026f95c ebp=0026f960
stackbase!b+0xa:
011a101a 83c404          add     esp,4
ebp=0026f960
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
02 0026f96c 011a107e stackbase!a+0xa
02 0026f96c 011a107e stackbase!a+0xa
eax=00000524 ebx=7ffd7000 ecx=00000524 edx=00000000 esi=011ea760 edi=003c9128
eip=011a103a esp=0026f968 ebp=0026f96c
stackbase!a+0xa:
011a103a 83c404          add     esp,4
ebp=0026f960
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
03 0026f97c 011a12e3 stackbase!main+0x2e
03 0026f97c 011a12e3 stackbase!main+0x2e
eax=00000524 ebx=7ffd7000 ecx=00000524 edx=00000000 esi=011ea760 edi=003c9128
eip=011a107e esp=0026f974 ebp=0026f97c
stackbase!main+0x2e:
011a107e 83c404          add     esp,4
ebp=0026f960
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
04 (Inline) -------- stackbase!invoke_main+0x1c
04 (Inline) -------- stackbase!invoke_main+0x1c
eax=00000524 ebx=7ffd7000 ecx=00000524 edx=00000000 esi=011ea760 edi=003c9128
eip=011a12e3 esp=0026f984 ebp=0026f9c4

这取决于你是如何编译的。是非易失性寄存器:是。在函数调用期间保存:否。保留调用方值的最简单方法是根本不触摸RBP。将其用作传统帧指针是可选的,并且超出了保留调用寄存器的要求。调试版本通常默认为
gcc-fno ommit frame pointer
或等效版本,但.Debug版本的性能较差…..我认为使用flag-fno ommit frame pointer会导致性能问题……是否有其他方法不接触RBP?…假设我们没有使用上述标志,我们可以假设.frame/r命令的输出将具有正确的RBP值吗?windows/Oy[-]的-fno省略帧指针的等效值仅对ia32有效……我猜Win64没有这样的标志。你是说MSVC?gcc和clang在Windows上都可以正常工作。“您可能还需要使用/c覆盖本地上下文,否则所有帧都将显示帧0的baseptr”-您可以详细说明这一点(覆盖本地上下文)吗(或)指向任何文档……我正在传递/c,但我仍然看到多个帧的相同RBP……这种行为在我的原始代码中可以看到……如果我在单机版中尝试,我会使每个帧的所有RBP都不同,我看到相同RBP重复三次,如下所示……我还看到.frame/r/c和.frame/r的相同输出。。。。。。rbp=000000 F088D264D0。rbp=000000 F088D266F0-->1。rbp=000000 F088D266F0-->1。rbp=000000 F088D27940。rbp=000000 F088D279D0。rbp=000000 F088D28E10。rbp=000000 F088D29C30。rbp=000000 F088D2Cf00。rbp=000000 F088D2DAD0。rbp=000000 F088D2EEE0。rbp=000000 F088D2F220。rbp=000000 F088D2F460-->2。rbp=000000 F088D2F460-->2。rbp=000000 F088D2F990-->3。rbp=000000 F088D2F990-->3。rbp=0000000000000000。rbp=0000000000000000。
0:000> !for_each_frame ".frame /r @$frame; r ebp"
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
00 0026f954 011a101a stackbase!c
00 0026f954 011a101a stackbase!c
eax=00000524 ebx=7ffd7000 ecx=00000524 edx=00000000 esi=011ea760 edi=003c9128
eip=011a1000 esp=0026f958 ebp=0026f954 
stackbase!c:
011a1000 55              push    ebp
ebp=0026f960
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
01 0026f960 011a103a stackbase!b+0xa
01 0026f960 011a103a stackbase!b+0xa
eax=00000524 ebx=7ffd7000 ecx=00000524 edx=00000000 esi=011ea760 edi=003c9128
eip=011a101a esp=0026f95c ebp=0026f960
stackbase!b+0xa:
011a101a 83c404          add     esp,4
ebp=0026f960
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
02 0026f96c 011a107e stackbase!a+0xa
02 0026f96c 011a107e stackbase!a+0xa
eax=00000524 ebx=7ffd7000 ecx=00000524 edx=00000000 esi=011ea760 edi=003c9128
eip=011a103a esp=0026f968 ebp=0026f96c
stackbase!a+0xa:
011a103a 83c404          add     esp,4
ebp=0026f960
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
03 0026f97c 011a12e3 stackbase!main+0x2e
03 0026f97c 011a12e3 stackbase!main+0x2e
eax=00000524 ebx=7ffd7000 ecx=00000524 edx=00000000 esi=011ea760 edi=003c9128
eip=011a107e esp=0026f974 ebp=0026f97c
stackbase!main+0x2e:
011a107e 83c404          add     esp,4
ebp=0026f960
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
04 (Inline) -------- stackbase!invoke_main+0x1c
04 (Inline) -------- stackbase!invoke_main+0x1c
eax=00000524 ebx=7ffd7000 ecx=00000524 edx=00000000 esi=011ea760 edi=003c9128
eip=011a12e3 esp=0026f984 ebp=0026f9c4