栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

x86

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

x86

您似乎在这里有两个问题:

  1. 返回值的高位在返回之前是否需要清零?(在调用之前,是否需要将参数的高位清零?)
  2. 与该决定相关的成本/收益是什么?

第一个问题的答案是 否定的, 高位 可能 有垃圾,并且PeterCordes已经就该主题写了一个非常好的答案。

至于第二个问题,我怀疑未定义高位总体上对性能更好。一方面,使用32位运算时,零扩展值无需付出任何额外费用。但是另一方面,并​​非总是需要事先将高位清零。如果允许高位垃圾,则可以将其留给接收值的代码,以便仅在实际需要时才执行零扩展(或符号扩展)。

但我想强调另一个考虑因素: 安全性

信息泄漏

当未清除结果的高位时,它们可能会在堆栈/堆中保留其他信息的片段,例如函数指针或地址。如果存在一种机制,可以执行更高特权的功能并在之后检索

rax
(或
eax
)的全部值,则可能会导致
信息泄漏
。例如,系统调用可能会将指针从内核泄漏到用户空间,从而导致内核ASLR失败。否则IPC机制可能会泄漏有关另一个进程的地址空间的信息,这可能有助于开发沙箱突破。

当然,也许有人会认为,防止信息泄漏不是ABI的责任;程序员应正确执行其代码。虽然我确实同意,但要求编译器将高位清零,仍然可以消除这种特殊形式的信息泄漏。

你不应该相信你的输入

另一方面,更重要的是,编译器不应盲目地相信任何接收到的值的高位都清零,否则函数可能无法按预期运行,这也可能导致可利用的条件。例如,考虑以下内容:

unsigned char buf[256];...__fastcall void write_index(unsigned char index, unsigned char value) {    buf[index] = value;}

如果允许我们假设

index
其高位清零,那么我们可以将上面的代码编译为:

write_index:  ;; sil = index, dil = value    mov rax, offset buf    mov [rax+rsi], dil    ret

但是,如果我们能够从我们自己的代码中调用这个函数,我们可以值提供

rsi
出的
[0,255]
范围,并写入到内存超出缓冲区的范围。

当然,编译器实际上不会生成这样的代码,因为如上所述, 被调用方 有责任对其参数进行零扩展或符号扩展,而不是 调用方的
参数扩展。我认为,这是一个非常实际的原因,要让接收值的代码始终假定高位有垃圾并明确将其删除。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/372708.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号