处理器的字节顺序和堆栈增长方向之间是否存在关系?
例如, x86架构是 little endian 并且堆栈向下增长(即它从最高地址开始,并在每次push
操作时向低地址增长)。同样,在 SPARC架构( big endian )中,堆栈从最低地址开始,向上移向更高的地址。
几乎在所有架构中都可以看到这种关系模式。 我认为这种未说明的约定必须有一个原因。这可以从计算机体系结构或操作系统的角度来解释吗?这是否适用于处理器内微码的某些优化?这会以某种方式帮助内核吗?或者可能是其他原因?
提前致谢!
答案 0 :(得分:2)
Endianness是一段数据的字节顺序。
考虑0x0A0B0C0D
的十六进制值,可以将其分为0x0A, 0x0B, 0x0C, 0x0D
的4个字节。
在记忆方面:
假设我们的内存地址为 o
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
使用堆栈,它会产生相反的字节序,因此,当我们从中弹出数据时,它会重新采用正确的字节顺序。这是另一个例子,但是使用了一个堆栈。
无符号数据= 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
答案 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的堆栈方向应该是什么才能使其工作?