assembly - Windows 堆栈上的“额外”32 个字节是什么?
问题描述
我正在 Windows 上学习汇编并试图弄清楚堆栈上的值是什么。Visual C++ 文档
说 RSP 以上的值是
:
- 分配空间
- 保存的 RBP
- 退货地址
- 寄存器主页(RCX、RDX、R8、R9)
- 功能参数
问题是文档中没有提到堆栈中有 32 个额外的字节。
在内存快照中,RSP 从 0x0000000000DAF5E0 开始。彩色框是:
- 黄色:两个 64 位变量,值为 9
- 白色:保存旧 RBP + 返回地址
- 蓝色:功能参数
- 绿色:注册家
- 红色的: ?
那些红色的字节可能是什么?
使用 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 调试模式用于毒化堆栈的值,有助于检测未初始化内存的读取。(如果你不小心用这些内容执行了内存,那就是 x86int3
调试断点指令。)
顺便说一句,当您使用 RBP 作为传统的帧指针时,//mov rsp, rbp
比pop rbp
/ret
更有效add rsp, 16
。pop rbp
代码大小略小,一些 CPU 会进行 mov-elimination 以避免mov
. 这对你来说会更吵,比如可能从你的调用者的返回地址返回,你可能在单步执行时已经注意到了!
( leave
= mov/pop,因此您可以将其用于更小的代码大小。这对于性能来说是可以的,不像enter
; GCCleave
在函数中使用以 RSP 结尾但尚未指向保存的 RBP 的帧指针。其他一些编译器更喜欢 mov /pop。但编译器通常只add rsp, n
在根本不使用帧指针时才使用。)
帧指针是可选的,并且不是堆栈帧布局的必需部分。诸如创建元数据之类的指令.allocstack 16
使堆栈展开成为可能,而无需传统的帧指针链表。
推荐阅读
- haskell - 是否可以返回一个依赖于 Maybe 类型值的函数
- c++ - 从 QTreeView 连接信号/插槽时出现问题
- ios - 我的 AppDelegate Swift 类在一个 Objective-C 文件中被识别,但在 main.m 中却没有。我该如何解决?
- wordpress - WordPress + Vimeo API | 通过 URI 查找特定视频
- django - Django 中的 Jsonresponse 在浏览器中工作,但不在 PostMan 或 Angular 中
- python - 在 selenium 下启动的浏览器不使用插件
- c# - Unity - www.isDone 总是返回 false
- casbin - 如何基于多组成员身份使用 Casbin 保护资源
- postgresql - 如何通知 pod(s) 其他副本 pod 的 IP 地址
- python - 如何在另一个文件夹中导入 Python 模块,而无需相对导入和编辑 PYTHONPATH