探究不同架构下向 C 函数传递过少寄存器参数的后果,安腾架构更严格!
微软开发博客导航微软开发博客提供了丰富的内容导航涵盖开发者相关、技术相关、编程语言相关、.NET 相关、平台开发相关、数据开发相关等多个方面。开发者相关包括面向开发者的微软、Visual Studio、Visual Studio Code 等技术相关有 DirectX、微软代理框架编程语言相关涉及 C、C#、F# 等.NET 相关包含所有 .NET 文章、.NET MAUI、AI 等平台开发相关有 #ifdef Windows、微软铸造厂等数据开发相关包括 Azure Cosmos DB、Azure Data Studio 等。探究传递过少寄存器参数的后果在探索 Windows 上各种处理器的调用约定时我们发现很多情况下部分参数是通过寄存器传递的。假设存在一个接受两个参数的函数若第一个参数为正数该函数会忽略第二个参数。那么只传递一个参数如传递零来调用这个函数会怎样呢从形式上来说C 和 C 语言规定以错误的参数数量调用函数其行为是未定义的。栈传递参数过少的问题如果在栈上传递的参数过少且采用被调用者清理栈的调用约定被调用者会从栈上清理过多的字节导致栈不平衡并可能导致内存损坏。即使不是被调用者清理栈的调用约定被调用函数也会认为参数的内存存在并可能将其用作临时存储空间从而导致调用函数的栈帧出现内存损坏。寄存器传递参数不足的情况若参数通过寄存器传递而传递的参数不足在大多数处理器上被调用函数会尝试使用该寄存器并读取其中未初始化的值。但安腾Itanium处理器是个例外它有“非有效事物”Not a ThingNaT位附加到每个通用寄存器用于指示该寄存器是否包含有效值。如果未初始化的输出寄存器恰好是早期失败推测遗留下来的 NaT被调用函数可能会在使用该寄存器做其他事情之前将该值保存到栈上。安腾架构的特殊情况在安腾架构中函数调用机制是架构层面的。调用函数会声明输出寄存器的数量且这些寄存器在进入被调用函数时会重新编号。如果向函数传递的参数过少默认栈帧包含的寄存器数量比函数预期的要少。从架构层面来说读取当前帧之外的栈寄存器结果是“未定义的”可能会引发处理器异常写入当前帧之外的栈寄存器必须引发非法操作错误。所以安腾架构更严格执行编程规则要确保向函数传递正确数量的参数。作者介绍雷蒙德参与 Windows 的发展已有 30 多年。2003 年他创建了“旧闻新谈”网站其受欢迎程度超出想象。该网站催生了一本书书名也叫《旧闻新谈》Addison Wesley2007 年。他偶尔会在 Windows 开发文档的 Twitter 账号上分享一些没有实际用处的故事。评论情况有两条评论肯·塞特尔指出修改后的第二个示例在第一个 if 语句块中应该返回 b 而不是 c约书亚·哈德森的评论未完整显示。