对 Windows 中历史悠久的 _chkstk 函数进行技术回顾,详细阐述了其针对 x86-32 和 16 位 8086 的独特“被调用者脏栈”(callee-dirty)调用约定和栈探测机制。
📝 详细摘要
Raymond Chen 的这篇文章探讨了 Windows 上栈限制检查的演变,重点关注 x86-32 (i386) 架构。文章深入探讨了最初的 _chkstk 函数,该函数采用了一种非常不寻常的“被调用者脏栈”调用约定,即函数返回时栈空间比调用前更大。作者解释了用于“触碰”每个内存页以触发保护页,从而确保栈有效性的汇编级逻辑。此外,文章通过审视 16 位 8086 的实现,提供了历史背景,强调了早期 Windows 系统中近调用和远调用的复杂性。
💡 主要观点
-
_chkstk 函数采用了一种独特的“被调用者脏栈”调用约定来管理栈增长。
与调用者或被调用者清理栈的标准约定不同,_chkstk 返回时栈指针已被修改,有效地为调用者分配了空间,同时确保每个内存页都得到正确初始化。
ecx 这样的寄存器,并使用 jmp 而非标准的 ret 来返回到调用者的执行流。
💬 文章金句
- 这是一种不寻常的调用约定,因为它既不是调用者清理,也不是被调用者清理。它是“被调用者脏栈”!
- 函数返回时栈空间比调用前更大。
- 函数触碰了栈的每个页,调整了栈指针,然后带着调整后的栈指针返回。
- 这可以参与“最古怪的 x86-32 调用约定”的竞争。
- 这种奇怪的调用约定可以追溯到 16 位 8086 时代。那时,
chkstk函数有两个版本,取决于你是进行远调用还是近调用。
📊 文章信息
AI 评分:82
来源:The Old New Thing
作者:Raymond Chen
分类:软件编程
语言:英文
阅读时间:3 分钟
字数:501
标签: Windows 内部原理, x86 汇编, 栈管理, 调用约定, 系统编程