【问题标题】:Are there any alive CPU architectures with two stacks today?今天有没有两个堆栈的活跃 CPU 架构?
【发布时间】:2015-12-27 14:00:38
【问题描述】:

通常使用两个堆栈来防止缓冲区溢出探索是否更简单? 一个堆栈用于变量和传递参数,另一个用于返回地址。

或者像 NX/XD-bits(在 AMD/Intel x86 上)这样的不可执行堆栈做得更好?

【问题讨论】:

  • 有些架构默认情况下不会将“跳转和链接”类型指令的返回地址推送到堆栈上,这算吗?您可以手动将其放在任何地方,包括“第二个堆栈”
  • 当然可以。使用寄存器窗口的体系结构,例如 SPARC 或 Itanium,浮现在脑海中。更直接的是,大量嵌入式 8 位 MCU,例如 PIC18F 系列,也使用专用的返回堆栈。
  • 跟进@harold 所说的,您可以在使用 push-return-address (x86) 的架构上执行此操作,方法是将数据堆栈放在其他位置。我实际上不知道有什么架构你不能这样做,这只是意味着扔掉一个寄存器名称。
  • @dwelch 6809 有两个堆栈指针,硬件堆栈和用户堆栈,带有PSHSPSHUPULSPULU 指令。这个Wikipedia page“2015 年底,Rochester 的 MC6809 进入制造阶段,预计将于 2016 年 7 月开始生产。”
  • 任何 CPU 架构都可以实现多个堆栈。您不限于使用 CPU 架构用于实现堆栈的任何特殊指令或寄存器(如果有)。如果您想在 ARM、x86 或 6502 CPU 上使用多个堆栈,那么没有什么可以阻止您。

标签: assembly cpu-architecture


【解决方案1】:

安腾有两个堆栈。我相信一个是用于存储局部变量(如数组和东西),而另一个是用于返回地址。这样,您就不能通过溢出缓冲区来覆盖返回地址。

https://blogs.msdn.microsoft.com/oldnewthing/20050421-28/?p=35833

【讨论】:

    【解决方案2】:

    32 位 ARM

    除了使用 r13 作为堆栈指针从一个完整的降序堆栈加载程序计数器之外,该指令集对于用作堆栈指针的寄存器或堆栈增长的方向是中立的。在汇编语言中,“push”和“pop”只是加载和存储指令的替代名称。

    Thumb 是 16 位宽的指令集,有一个首选的堆栈指针,但其他寄存器也同样可以使用。

    问题是多个堆栈需要多个推送/弹出指令。

    AVR

    没有指令可以对堆栈指针进行加减运算,也没有指令可以原子地将堆栈指针设置为新值。因此创建堆栈帧可能涉及:

    1. 加载堆栈指针的低字节。
    2. 加载堆栈指针的高字节。
    3. 执行 16 位减法。
    4. 保存中断启用状态。
    5. 禁用中断。
    6. 存储堆栈指针的高字节。
    7. 存储堆栈指针的低字节。
    8. 恢复中断启用状态。

    未能禁用中断可能会导致 200 字节的 RAM 被浪费,从而导致堆栈溢出。 (有些 AVR 型号有 1024 字节的 RAM)

    至少有一个 C 编译器使用一对通用寄存器作为数据堆栈指针,可以原子地添加或减去。

    【讨论】:

    • 其他一些 RISC ISA 对堆栈指针完全中立;例如MIPS 没有任何推送/弹出指令,因此您必须为$sp 或您选择的任何其他寄存器自己做。即使在像 x86 这样的 ISA 上,您可以手动修改另一个 reg 作为第二个堆栈指针;推/流行不是魔术。问题还在于这些平台上的标准 ABI 是否确实使用 2 个堆栈将返回地址与自动存储分开。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-19
    • 2016-01-12
    • 1970-01-01
    • 1970-01-01
    • 2021-05-23
    • 1970-01-01
    相关资源
    最近更新 更多