Embedded 竖直度与堆栈生长方向的关系

Embedded 竖直度与堆栈生长方向的关系,embedded,cpu-architecture,endianness,callstack,Embedded,Cpu Architecture,Endianness,Callstack,处理器的端度和堆栈增长方向之间有关系吗 例如,x86体系结构是小端数,堆栈向下增长(即,它从最高地址开始,随着每次推送操作向较低地址增长)。类似地,在SPARC体系结构中(即big-endian),堆栈从最低地址开始,向上扩展到更高的地址 几乎在所有体系结构中都可以看到这种关系模式。我相信这种未被提及的惯例一定有其原因。这可以从计算机体系结构或操作系统的角度来解释吗?这是为了优化处理器内部的微代码吗?这在某种程度上有助于内核吗?或者可能是其他原因 提前谢谢 Endianness是一段数据的字节顺

处理器的端度和堆栈增长方向之间有关系吗

例如,x86体系结构是小端数,堆栈向下增长(即,它从最高地址开始,随着每次
推送
操作向较低地址增长)。类似地,在SPARC体系结构中(即big-endian),堆栈从最低地址开始,向上扩展到更高的地址

几乎在所有体系结构中都可以看到这种关系模式。我相信这种未被提及的惯例一定有其原因。这可以从计算机体系结构或操作系统的角度来解释吗?这是为了优化处理器内部的微代码吗?这在某种程度上有助于内核吗?或者可能是其他原因


提前谢谢

Endianness是一段数据的字节顺序

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

在记忆方面:

假设我们的内存地址为o

对于big-endian,顺序是第一个字节始终是第一个:
内存[o]=0x0A

内存[o+1]=0x0B

内存[o+2]=0x0C

内存[o+3]=0x0D

对于little endian,第一个字节放入最远的偏移量:
内存[o]=0x0D

内存[o+1]=0x0C

内存[o+2]=0x0B

内存[o+3]=0x0A

使用堆栈时,它的端点方向相反,因此当我们从堆栈中弹出数据时,它会重新采用正确的端点顺序。这里是另一个例子,但使用堆栈

小端栈 无符号数据=0x0A0B0C0D

&data=0x0D

&数据+1=0x0C

&data+2=0x0B

&data+3=0x0A

当我们推送数据时,由于堆栈是LIFO/FILO,所以数据的小尾端存储为大尾端,因此popping保留了尾端,因此:

[ebp]==0x0A

[ebp-1]==0x0B

[ebp-2]==0x0C

[ebp-3]==0x0D


TLDR:堆栈是系统的相反端。堆栈生长方向与整数端正交。

更宽整数(字)中的字节顺序与堆栈推送是否从堆栈指针进行加法或减法之间存在零连接。就推送而言,存储数据是一个操作

将寄存器宽度整数映射到内存中的字节使用不同于堆栈指针inc/dec逻辑的硬件;我假设正常的设计是使用非推送/弹出存储/加载所经过的相同硬件,并将推送存储与任何其他“单词”存储一样对待。没有任何一种奇怪的一次一个字节的方式来逐个递增堆栈指针

几乎在所有体系结构中都可以看到这种关系模式

嗯,不是真的。许多现代RISC ISA(例如MIPS、PowerPC、ARM)都有可选的Endianness 1,这与堆栈增长方向无关

显示在大多数主流系统上,堆栈增长方向通常是按惯例或按需求下降的,包括在big-endian系统上

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

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

我们可以解释的是,向下是事实上的标准。IDK为什么SPARC不厌其烦地向上选择。堆栈位于可用内存的顶部,静态代码/数据位于固定地址的底部,显然是自然的,没有分页/虚拟内存

我们就是这样来到这里的

在某些ISA(例如MIPS)上,堆栈增长方向完全由软件决定。硬件没有隐式/异步地使用堆栈,也没有push/pop指令使它更高效地执行某种方式

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

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

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


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



脚注1:一些特定的ARM或MIPS CPU的endianness是硬连线的,不能在运行时选择,因为这基本上是一个无用的功能,是对嵌入式芯片的浪费。不确定现代电源硬件;Godbolt compiler explorer()既有PowerPC64也有PowerPC64le编译器,但这不能告诉我们它们是否仍然相关。

注意:嵌入式PIC24系列处理器似乎是反例:“(堆栈指针)从较低的地址增长到较高的地址”,整数是小端数。这完全是胡说八道。堆栈增长方向与整数端度正交,您的x86示例(
[ebp-0..3]
未对齐,32位存储在地址
[ebp-3]
处。如果我们假设使用传统堆栈帧,这将在保存的ebp值中重叠一个字节。实际上,
推送将使数据保留在
[ebp-4]
=
[esp]
,如果在