assembly - 大多数现代系统中堆栈增长的方向是什么?

标签 assembly stack callstack abi stack-frame

我正在准备一些 C 语言培训 Material ,我希望我的示例适合典型的堆栈模型。

C 堆栈在 Linux、Windows、Mac OSX(PPC 和 x86)、Solaris 和最新的 Unix 中朝什么方向发展?

最佳答案

堆栈增长通常并不取决于操作系统本身,而是取决于其运行的处理器。例如,Solaris 在 x86 和 SPARC 上运行。 Mac OSX(正如您所提到的)在 PPC 和 x86 上运行。 Linux 可以运行在从我工作中的 System z 到 puny little wristwatch 的所有东西上。

如果 CPU 提供任何类型的选择,那么如果您希望自己的代码调用其他人的代码,则操作系统使用的 ABI/调用约定会指定您需要做出的选择。

处理器及其方向是:

  • x86:向下。
  • SPARC:可选。标准 ABI 使用羽绒。
  • PPC:我认为下降了。
  • System z:在一个链接列表中,我没有骗你(但仍然处于关闭状态,至少对于 zLinux 而言)。
  • ARM:可选,但 Thumb2 仅具有向下的紧凑编码(LDMIA = 之后递增,STMDB = 之前递减)。
  • 6502:向下(但只有 256 字节)。
  • RCA 1802A:您想要的任何方式,均以 SCRT 实现为准。
  • PDP11:下降。
  • 8051:向上。
<小时/>

最后几台显示了我的年龄,1802 是用于控制早期航天飞机的芯片(我怀疑,根据它的处理能力来感应门是否打开:-) 和我的第二台计算机,COMX-35 (跟随我的 ZX80 )。

here 收集 PDP11 详细信息,从 here 收集 8051 详细信息。

SPARC架构采用滑动窗口寄存器模型。架构上可见的细节还包括寄存器窗口的循环缓冲区,该缓冲区有效并在内部缓存,在上溢/下溢时带有陷阱。详细信息请参见 here。如 the SPARCv8 manual explains , SAVE 和 RESTORE 指令就像 ADD 指令加上寄存器窗口旋转。使用正常量而不是通常的负常量将产生向上增长的堆栈。

前面提到的 SCRT 技术是另一种 - 1802 使用一些或十六个 16 位寄存器用于 SCRT(标准调用和返回技术)。一是程序计数器,您可以使用SEP Rn指令将任何寄存器用作PC。一个是堆栈指针,两个总是指向 SCRT 代码地址,一个用于调用,一个用于返回。 没有寄存器以特殊方式处理。请记住,这些细节来自内存,它们可能不完全正确。

例如,如果 R3 是 PC,R4 是 SCRT 调用地址,R5 是 SCRT 返回地址,R2 是“堆栈”(在软件中实现时引用),SEP R4会将 R4 设置为 PC 并开始运行 SCRT 调用代码。

然后它将把 R3 存储在 R2“堆栈”上(我认为 R6 用于临时存储),向上或向下调整它,抓取 R3 后面的两个字节,将它们加载到 R3 中,然后执行 SEP R3 并在新地址运行。

要返回,它将SEP R5从R2堆栈中拉出旧地址,向其添加两个(以跳过调用的地址字节),将其加载到R3和SEP R3 开始运行之前的代码。

在所有基于 6502/6809/z80 堆栈的代码之后,一开始很难理解,但仍然以一种令人头晕目眩的方式优雅。该芯片的一大卖点是全套 16 个 16 位寄存器,尽管您立即丢失了其中 7 个(5 个用于 SCRT,两个用于 DMA 和内存中断)。啊,营销战胜现实:-)

System z 实际上非常相似,使用其 R14 和 R15 寄存器进行调用/返回。

关于assembly - 大多数现代系统中堆栈增长的方向是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/664744/

相关文章:

c - 汇编程序中eax寄存器的值

stack - LTE堆栈协议(protocol)开发

java - 如何查看堆栈中的特定项目?

go - 如何通过运行时获取真实文件名。不同goroutine中匿名函数调用的调用者

c# - 如何验证调用堆栈上的参数 "high up"?

c++ - 将汇编代码与 c/c++ 混合

c++ - 使用指针将代码翻译成 Pascal 中的程序集 - Delphi

assembly - MOV 和 LEA 有什么区别?

stack - 如何从 MIPS 程序集中的堆栈中弹出?

callstack - 简而言之解释堆栈框架的概念