端序和堆栈生长方向之间的关系



处理器的端序与堆栈增长方向之间是否存在关系?

例如,x86体系结构little-endian,堆栈向下增长(即,它从最高地址开始,并随着每次push操作而向较低地址增长)。类似地,在SPARC体系结构中,即big-endian,堆栈从最低地址开始,并向上向更高的地址增长。

这种关系模式几乎出现在所有架构中 我认为这种未公开的惯例一定有原因。这可以从计算机体系结构或操作系统的角度来解释吗?这是为了在处理器内部的微码中进行一些优化吗?这在某种程度上有助于内核吗?或者可能是其他原因?

提前感谢!

堆栈生长方向与整数字节序正交

在更宽的整数(字)中的字节顺序与堆栈推送是向堆栈指针添加还是从堆栈指针中减去之间没有任何联系。就推送而言,存储数据只是一个操作。

将寄存器宽度整数映射到存储器中的字节使用与堆栈指针inc/dec逻辑不同的硬件;我认为正常的设计是使用与非推送/弹出存储/加载相同的硬件;单词";。不是任何一种奇怪的每次一个字节递增堆栈指针的事情。

这种关系模式几乎出现在所有体系结构中。

嗯,不是真的。许多现代RISC ISA(例如MIPS、PowerPC、ARM)具有可选的端序1,而与堆栈生长方向无关。

在大多数现代系统中,堆栈增长的方向是什么?显示,在大多数主流系统上,堆栈增长方向通常会根据惯例或需求而下降,包括在big-endian系统上。

根据该问答的回答;A、 SPARC上的主流操作系统/ABI选择向下扩展堆栈。向上是SPARC的一个选项,但与其他系统一样,正常的选择是向下。

这可以从计算机体系结构或操作系统的角度来解释吗?

我们可以解释的是,向下是事实上的标准。IDK为什么SPARC愿意做出向上的选择。堆栈在可用内存的顶部,静态代码/数据在固定地址的底部,显然在没有分页/虚拟内存的情况下是自然的。https://softwareengineering.stackexchange.com/questions/137640/why-does-the-stack-grow-downward

所以我们就是这样来到这里的。

在一些ISAs(例如MIPS)上,堆栈生长方向完全由软件决定。硬件不会隐式/异步地使用堆栈,也没有推送/弹出指令可以使其更高效地执行某种方式。

但正常的选择仍然是向下的。

其他ISAs类似于x86,异步中断将内容推送到内核堆栈上,强制执行一个方向。或者至少在一种方式上有偏差,通过为一个方向提供有效的推送/弹出(如ARM Thumb和x86的push/pop)。更不用说x86的call/ret指令,它们推送/弹出一个返回地址,而不仅仅是写入一个链接寄存器。

如果没有方向选择,在大多数ISA中,一个固定的方向是向下的,但@chux评论说PIC24有向上的堆栈增长。


我确信所有这些都有大端和小端的例子,或者至少双端系统可以配置为大端或小端。


脚注1:一些特定的ARM或MIPS CPU的端序是硬连接的,而不是运行时可选择的,因为这基本上是一个无用的功能,也是对嵌入式硅的浪费。不确定现代POWER硬件;Godbolt编译器资源管理器(https://godbolt.org/)有PowerPC64和PowerPC64le编译器,但这并不能告诉我们它们是否仍然相关。

Endianness是一段数据的字节顺序。

考虑其中CCD_ 6的十六进制值可以划分为CCD_ 7的4个字节。

在内存方面:

假设我们有一个o的内存地址

对于big-endian,顺序是第一个字节总是第一个:

memory[o] = 0x0A

memory[o+1] = 0x0B

memory[o+2] = 0x0C

memory[o+3] = 0x0D

对于little-endian,第一个字节被放入最远的偏移量:

memory[o] = 0x0D

memory[o+1] = 0x0C

memory[o+2] = 0x0B

memory[o+3] = 0x0A

对于堆栈,它采用相反的端序,因此,当我们从中弹出数据时,它会重新采用正确的端序。这是另一个使用堆栈的示例。

Little endian堆栈

无符号数据=0x0A0B0C0D;

&data = 0x0D

&data+1 = 0x0C

&data+2 = 0x0B

&data+3 = 0x0A

当我们push data时,由于堆栈是LIFO/FILO,数据的小端序被存储为大端序,因此popping保留了端序,从而:

[ebp] == 0x0A

[ebp-1] == 0x0B

[ebp-2] == 0x0C

[ebp-3] == 0x0D

TLDR:堆栈是系统的相反端序

最新更新