字节序与堆栈增长方向之间的关系

时间:2013-08-27 15:43:31

标签: architecture linux-kernel embedded processor computer-architecture

处理器的字节顺序和堆栈增长方向之间是否存在关系?

例如, x86架构 little endian 并且堆栈向下增长(即它从最高地址开始,并在每次push操作时向低地址增长)。同样,在 SPARC架构 big endian )中,堆栈从最低地址开始,向上移向更高的地址。

几乎在所有架构中都可以看到这种关系模式。 我认为这种未说明的约定必须有一个原因。这可以从计算机体系结构或操作系统的角度来解释吗?这是否适用于处理器内微码的某些优化?这会以某种方式帮助内核吗?或者可能是其他原因?

提前致谢!

3 个答案:

答案 0 :(得分:2)

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

考虑0x0A0B0C0D的十六进制值,可以将其分为0x0A, 0x0B, 0x0C, 0x0D的4个字节。

在记忆方面:

假设我们的内存地址为 o

对于big endian,顺序是第一个字节始终是第一个:

memory[o] = 0x0A

memory[o+1] = 0x0B

memory[o+2] = 0x0C

memory[o+3] = 0x0D

对于小端,第一个字节放入最远的偏移量:

memory[o] = 0x0D

memory[o+1] = 0x0C

memory[o+2] = 0x0B

memory[o+3] = 0x0A

使用堆栈,它会产生相反的字节序,因此,当我们从中弹出数据时,它会重新采用正确的字节顺序。这是另一个例子,但是使用了一个堆栈。

Little endian Stack

无符号数据= 0x0A0B0C0D;

&data = 0x0D

&data+1 = 0x0C

&data+2 = 0x0B

&data+3 = 0x0A

当我们push data时,数据的小端字节存储为大端,因为堆栈是LIFO / FILO因此弹出保留了字节序,因此:

[ebp] == 0x0A

[ebp-1] == 0x0B

[ebp-2] == 0x0C

[ebp-3] == 0x0D

TLDR:堆栈是系统的相反字节序。

答案 1 :(得分:2)

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

在较宽的整数(字)中的字节顺序与堆栈压入是从堆栈指针加还是减之间存在零连接。就推送而言,存储数据只是一个操作。

将寄存器宽度的整数映射到内存中的字节会使用与堆栈指针inc / dec逻辑不同的硬件;我假设正常的设计将使用非推送/弹出存储/加载所经历的相同硬件,并且像对待“ word”的任何其他存储一样,从推送中对待存储。不会出现一种奇怪的每次只能一个字节地递增堆栈指针的事情。

  

这种关系模式在几乎所有架构中都可见。

嗯,不是真的。许多现代RISC ISA(例如MIPS,PowerPC,ARM)具有可选的字节序 1 ,并且与堆栈增长方向有关。

What is the direction of stack growth in most modern systems?表明,在大多数主流系统上,堆栈增长方向通常是按照惯例或根据要求而降低的,包括大端系统。

根据该问答的答案,SPARC上的主流OS / ABI选择向下扩展堆栈。在SPARC上可以选择“向上”,但是像其他系统一样,通常的选择是“向下”。

  

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

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

这就是我们到这里的方式。

在某些ISA上,例如MIPS,堆栈增长方向完全由软件确定。硬件不会隐式地/异步地使用堆栈,也没有推/弹出指令可以使一种方法或另一种方法更有效。

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

其他ISA类似于x86,异步中断将内容推入内核堆栈,从而强制一个方向。或至少以一种方式产生偏见,方法是为一个方向提供有效的推入/弹出操作(例如ARM Thumb和x86的push / pop)。更不用说x86的call / ret指令,它推/弹出一个返回地址,而不仅仅是编写链接寄存器。

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


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


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

答案 2 :(得分:-1)

考虑可能用于字符串操作的这一系列指令:

push 32-bit zero

Loop:
write 8-bit char to the stack pointer
read 32-bit integer from the stack pointer

相对于endianess的堆栈方向应该是什么才能使其工作?