当前位置: 首页 > 知识库问答 >
问题:

Windows堆栈上的“额外”32个字节是什么?

班思源
2023-03-14

我在学Windows上的汇编,想弄清楚栈上的值是什么。< br > Visual C #文档说明高于RSP的值是:

  • 分配空间
  • 保存了RBP
  • 返回地址
  • 注册主页(RCX、RDX、R8、R9)
  • 函数参数

问题是堆栈中有32个额外的字节,文档中没有提到。

在内存快照中,RSP从0x0000000000DAF5E0开始。彩色框为:

  • 黄色:两个值为9的64位变量
  • 白色:保存旧RBP返回地址
  • 蓝色:函数参数
  • 绿色:注册回家
  • 红色:?

红色的字节可能是什么?

使用 VS2019、MASM64 构建并在 x64 调试模式下运行的 MASM 源代码。

c flags:/JMC/permissive-/GS/W3/Zc:wchar _ t/ZI/Gm-/Od/SDL/Fd " x64 \ Debug \ VC 142 . pdb "/Zc:inline/Fp:precise/D " _ Debug "/D " _ CONSOLE "/D " _ UNICODE "/D " UNICODE "/error report:prompt/WX-/Zc:for scope/RTC 1/Gd/MDd/FC/Fa " x64 \ Debug \ "/EHsc/no logo/Fo " x64 \ Debug \ "/x64

.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

共有1个答案

杭英杰
2023-03-14

您忘记执行< code>mov rbp,rsp(在< code>push rbp之后)来使rbp成为堆栈帧的帧指针。

你的“家庭空间”也就是影子空间比你的返回地址高32字节,你只是没有使用它。(相反,通过存储可能具有任何值的相对于某个寄存器的内容,违反了调用约定。在这种情况下,您的调用者可能也使用RBP作为遗留帧指针,所以您可能只是在踩调用者的主空间。)

请注意,0xCC是 MSVC 调试模式用于毒害堆栈的值,这有助于检测未初始化内存的读取。(如果您不小心使用这些内容执行内存,则为 x86 int3 调试断点指令。

顺便说一下,当您使用RBP作为传统的帧指针时,< code>mov rsp,RBP /< code > pop RBP /< code > ret 比< code>add rsp,16 / pop rbp更有效。代码规模稍小,一些CPU进行mov消除,以避免需要< code>mov的执行单元。这对你来说会有更大的噪音,就像从你的调用者的返回地址返回,这在单步执行时你可能已经注意到了!

(< code>leave = mov/pop,因此您可以将它用于更小的代码大小。性能上还行,不像< code > enter ;GCC在带有帧指针的函数中使用< code>leave,该函数以RSP尚未指向保存的RBP结束。其他一些编译器更喜欢mov/pop。但是编译器通常只在根本不使用框架指针时才使用< code>add rsp,n。)

帧指针是可选的,不是堆栈-帧布局的必需部分。. allocstack 16等指令创建的元数据使堆栈展开成为可能,而无需传统的帧指针链表。

 类似资料:
  • 问题内容: 我在标准Windows命令窗口中有一个正在运行的Java进程。即我已经运行’cmd’并在java -jar中键入… 我需要尽可能获得所有线程的完整堆栈转储。 我记得在Linux下,您可以通过quit命令上的选项将消息发送到JVM。 在此文件中为太阳状态 若要在Windows 95或Windows NT平台上生成堆栈跟踪,请在运行Java程序的窗口中输入键序列,或单击窗口上的“关闭”按钮

  • 问题内容: 我一直在使用请求/应用程序上下文有一段时间,但并没有完全了解它的工作原理或设计原因。当涉及到请求或应用程序上下文时,“堆栈”的目的是什么?这是两个单独的堆栈,还是都是一个堆栈的一部分?是将请求上下文压入堆栈,还是堆栈本身?我是否可以在彼此之上推送/弹出多个上下文?如果是这样,我为什么要这样做? 抱歉所有问题,但是阅读了请求上下文和应用程序上下文文档后,我仍然感到困惑。 问题答案: Mu

  • 问题内容: 当我尝试在套接字上使用sax解析xml时,遇到了一种奇怪的情况。经过分析,我注意到DataOutputStream在我的数据前面添加了2个字节。 DataOutputStream发送的消息: 使用Transformer发送消息: 可能已经注意到,DataOutputStream在消息前面添加了两个字节。因此,sax解析器将引发异常“ org.xml.sax.SAXParseExcept

  • 问题内容: 我正在阅读有关JVM体系结构的信息。今天,我了解了操作数堆栈的概念。根据一篇文章: 在字节码指令执行期间使用操作数堆栈,其方式与在本机CPU中使用通用寄存器的方式类似。 我不明白:操作数堆栈到底是什么,以及它在jvm中如何工作? 问题答案: 这是各种单个字节码操作如何获取其输入以及它们如何提供其输出的方式。 例如,考虑将两个s相加的运算。要使用它,您将两个值压入堆栈,然后使用它: 现在

  • 问题内容: 最近,我一直在寻找Java虚拟机规范(JVMS),以试图更好地理解使我的程序正常工作的原因,但是我找到了一段我不太了解的部分… 第4.7.4节介绍了 StackMapTable 属性,在该节中,文档介绍了有关堆栈映射框架的详细信息。问题是它有点罗word,我以身作则,学得最好。不读书。 我知道第一个堆栈映射框架是从方法描述符派生的,但是我不知道如何(应该在这里进行解释。)而且,我也不完

  • 我有一个关于书库的问题...我想写一个有3个堆栈的程序,我想在每个堆栈上添加这些操作(我应该使用数组): 1.创建堆栈2。按3号。流行音乐4号。显示每个堆栈的顶部 我写的程序,但我遇到了这些错误: 错误4错误LNK2019:未解析的外部符号“public:int\u thiscall stack::IsFull2(void)”(?IsFull2@stack@@QAEHXZ)在函数“public:v