我正在学习Windows上的程序集,并试图弄清楚堆栈上的值是什么。Visual C++ documentation说RSP之上的值是:
问题是文档中没有提到堆栈中有32个额外的字节。
在memory snapshot中,RSP从0x0000000000DAF5E0开始。彩色框是:
红色的那些字节可能是什么?
使用VS2019,MASM64构建并以x64调试模式运行的MASM源代码。
C ++标志:/ JMC / permissive- / GS / W3 / Zc:wchar_t / ZI / Gm- / Od / sdl /Fd"x64\Debug\vc142.pdb“ / Zc:inline / fp:precise / D” _DEBUG “ / D” _CONSOLE“ / D” _UNICODE“ / D” UNICODE“ / errorReport:prompt / WX- / Zc:forScope / RTC1 / Gd / MDd / FC / Fa” x64 \ Debug \“ / EHsc / nologo / Fo” x64 \ Debug \“ /Fp"x64\Debug\ConsoleApplication1.pch” / diagnostics:column
.code
; int64_t StackFrameDemo_(int8_t a, int16_t b, int32_t c, int64_t d, int8_t e, int16_t f, int32_t g, int64_t h)
StackFrameDemo_ proc frame
; prolog
push rbp
.pushreg rbp
; allocate 16 bytes on the stack
sub rsp, 16
.allocstack 16
.endprolog
; save registers to register home
mov qword ptr [rbp+8], rcx
mov qword ptr [rbp+16], rdx
mov qword ptr [rbp+24], r8
mov qword ptr [rbp+32], r9
; save the two variables
mov rax, 9
mov [rsp], rax
mov [rsp+type qword], rax
nop ; set the break point here to view memory
; epilog
add rsp, 16 ; release local stack space
pop rbp ; restore caller's rbp register
ret
StackFrameDemo_ endp
end
您忘记进行mov rbp, rsp
(在push rbp
之后),使RBP成为您的堆栈帧中的帧指针。
您的“家庭空间”又名影子空间是返回地址上方32字节,您只是不使用它。(并且通过存储相对于某些可能具有寄存器的寄存器而违反了调用约定。任何值。在这种情况下,您的呼叫者可能还将RBP用于旧式帧指针,因此您可能只是踩到了呼叫者的本地空间。)
请注意,0xCC
是MSVC调试模式用来中毒堆栈的值,有助于检测未初始化内存的读取。 (并且,如果您不小心用这些内容执行了内存,那是x86 int3
调试断点指令。)
[顺便说一句,当您将RBP用作传统的帧指针时,mov rsp, rbp
/ ret
比add rsp, 16
更有效。代码大小略小,某些CPU进行了移动消除,以避免需要mov
的执行单元。对于您来说,这可能会更吵闹,例如,可能是从呼叫者的寄信人地址返回,单步执行时您可能已经注意到了!