今天是否有任何具有两个堆栈的 CPU 架构?

Are there any alive CPU architectures with two stacks today?

一般用两个栈来防止缓冲区溢出探索是不是更简单? 一个用于变量和传递参数的堆栈,另一个用于 return 地址。

或者像 NX/XD-bits(在 AMD/Intel x86 上)这样的东西作为不可执行的堆栈会更好吗?

Itanium 有两个堆栈。我相信一个用于存储局部变量(如数组和其他东西),而另一个用于 return 地址。这样,您就无法通过溢出缓冲区来覆盖 return 地址。

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

32 位 ARM

除了使用 r13 作为堆栈指针从完整的递减堆栈加载程序计数器被视为 return 用于分支预测目的之外,指令集对于用作堆栈指针的寄存器是中性的或堆栈增长的方向。在汇编语言中,"push" 和 "pop" 只是加载和存储指令的替代名称。

16 位宽指令集 Thumb 具有首选堆栈指针,但其他寄存器也同样适用。

问题是多个堆栈需要多个 push/pop 指令。

AVR

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

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

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

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