← 回總覽

Windows 栈限制检查回顾:x86-32,又称 i386

📅 2026-03-13 06:18 Raymond Chen 软件编程 2 分鐘 1330 字 評分: 82
Windows 内部原理 x86 汇编 栈管理 调用约定 系统编程
📌 一句话摘要 对 Windows 中历史悠久的 `_chkstk` 函数进行技术回顾,详细阐述了其针对 x86-32 和 16 位 8086 的独特“被调用者脏栈”(callee-dirty)调用约定和栈探测机制。 📝 详细摘要 Raymond Chen 的这篇文章探讨了 Windows 上栈限制检查的演变,重点关注 x86-32 (i386) 架构。文章深入探讨了最初的 `_chkstk` 函数,该函数采用了一种非常不寻常的“被调用者脏栈”调用约定,即函数返回时栈空间比调用前更大。作者解释了用于“触碰”每个内存页以触发保护页,从而确保栈有效性的汇编级逻辑。此外,文章通过审视 16 位

📌 一句话摘要

对 Windows 中历史悠久的 _chkstk 函数进行技术回顾,详细阐述了其针对 x86-32 和 16 位 8086 的独特“被调用者脏栈”(callee-dirty)调用约定和栈探测机制。

📝 详细摘要

Raymond Chen 的这篇文章探讨了 Windows 上栈限制检查的演变,重点关注 x86-32 (i386) 架构。文章深入探讨了最初的 _chkstk 函数,该函数采用了一种非常不寻常的“被调用者脏栈”调用约定,即函数返回时栈空间比调用前更大。作者解释了用于“触碰”每个内存页以触发保护页,从而确保栈有效性的汇编级逻辑。此外,文章通过审视 16 位 8086 的实现,提供了历史背景,强调了早期 Windows 系统中近调用和远调用的复杂性。

💡 主要观点

- _chkstk 函数采用了一种独特的“被调用者脏栈”调用约定来管理栈增长。 与调用者或被调用者清理栈的标准约定不同,_chkstk 返回时栈指针已被修改,有效地为调用者分配了空间,同时确保每个内存页都得到正确初始化。

通过“触碰”每个内存页来触发保护页异常,从而执行栈探测。 该函数遍历请求的分配大小,访问每个 4KB 的页。这种机制确保 Windows 内核能够在应用程序使用空间之前扩展栈的已提交内存并处理栈溢出情况。
该实现涉及复杂的汇编级指令指针和寄存器操作。 由于函数会改变栈指针,它必须手动保存和恢复返回地址以及像 ecx 这样的寄存器,并使用 jmp 而非标准的 ret 来返回到调用者的执行流。
这些架构模式在 Windows 开发的 16 位 8086 时代就已根深蒂固。 栈检查的设计从早期的 16 位系统演变而来,当时针对近调用和远调用存在不同的版本,这表明了 Windows 生态系统中的长期连续性和遗留约束。

💬 文章金句

- 这是一种不寻常的调用约定,因为它既不是调用者清理,也不是被调用者清理。它是“被调用者脏栈”!

  • 函数返回时栈空间比调用前更大。
  • 函数触碰了栈的每个页,调整了栈指针,然后带着调整后的栈指针返回。
  • 这可以参与“最古怪的 x86-32 调用约定”的竞争。
  • 这种奇怪的调用约定可以追溯到 16 位 8086 时代。那时,chkstk 函数有两个版本,取决于你是进行远调用还是近调用。

📊 文章信息

AI 评分:82

来源:The Old New Thing

作者:Raymond Chen

分类:软件编程

语言:英文

阅读时间:3 分钟

字数:501

标签: Windows 内部原理, x86 汇编, 栈管理, 调用约定, 系统编程

阅读完整文章

查看原文 → 發佈: 2026-03-13 06:18:26 收錄: 2026-03-13 08:00:41

🤖 問 AI

針對這篇文章提問,AI 會根據文章內容回答。按 Ctrl+Enter 送出。