在讨论32位MIPS体系结构时,Patterson--Hennessy解释静态数据段开始于0x 1000 0000
,结束于0x 1000 FFFF
,全局指针$gp
默认设置为中间地址0x 1000 8000
,说明堆是下一个,因此应该开始于0x 1001 0000
。
然而,一些对MARS的实验告诉我,有一个 * 额外的 * 段位于两者之间,从0x 1001 0000
到0x 1003 FFFF
,所以堆只从0x 1004 0000
开始。实际上,当我使用syscall在堆上存储一个数组时,这个数组将存储在0x 1004 0000
之后。
当我在程序的.data
头下初始化数据时,这个额外的段似乎被使用了。这让我很困惑,因为我期望在.data
下初始化的数据被认为是静态的,因此应该被存储在由全局指针控制的段中。
**问题。**MARS标准是否表现出这种行为?如果是,位于静态数据和堆之间的这个附加数据段与位于其前面的静态数据段有何不同?
2条答案
按热度按时间2izufjch1#
我只是偶然发现了这段对话。我是MARS的主要开发者,现在已经退休好几年了。当我们在2004年开始MARS项目时,我们的主要目标之一是与当时主导MIPS模拟器市场的SPIM兼容。在SPIM中,如果您使用“.data”表示静态数据,那么请在它后面加上,比如说“a:.word 1”,变量a将被存储在0x 10010000。所以我写了MARS来做同样的事情。从来没有想过这一点。18年来没有人写信给我关于这一点(我的电子邮件地址在MARS帮助中,仍然有效)。我同意它应该是0x 10000000,但我不会改变它。干杯!
edqdpe6u2#
你不能把这些模拟器太当真。
我不知道为什么你不能在内存中移动东西。链接器需要知道全局数据符号的位置,这样它才能重新定位,但除此之外,处理器并不关心。
举例来说,MARS在“设置”中有一个“内存配置”选项,因此,例如,您可以将模拟器设置为具有有限内存(如64 k)的嵌入式处理器。
在真实的系统中,全局数据将由操作系统程序加载器从程序可执行文件中加载,数据部分将被放大
.bss
数量(最初为零),然后,通常,堆将在下一页边界开始。模拟器不做这些细节--它对所有程序都使用固定的内存模型;因此,它不会像真实的系统那样,根据程序集中全局变量的实际数量重新调整堆的起始位置。
因此,在我看来,它只是为汇编程序使用的全局存储保留了256 k。
前64 k保留用于使用
$gp
直接访问,但默认情况下MARS不会在其中放置任何全局数据,如果强制数据从0x 10000000开始(通过.data 0x10000000
),您可以在那里放置符号,但执行lw $t0, label($gp)
(其中label
驻留在$gp
的16位范围内)被视为伪指令(扩展为3条指令),将label
的绝对值与$gp
中的值相加,然后执行lw
-这将无法正确访问全局数据,b/c$gp
保存0x 10008000,因此,当它应该改为添加label
相对于$gp
的偏移量时,它将结束添加两个指针。如果真的想要通过使用$gp
的适当的1指令序列来使用全局数据,(使用默认的内存配置模型)您可以使用.eqv
定义常量,而不是定义标签,并自己管理偏移量(yuk,但适用于小程序)。相反,MARS将
.data
的默认起始位置设置为0x 10010000,我认为这只是为了避免64 k的$gp
可访问区域。任何使用数据标签的指令都被扩展为使用以lui
开头的多指令序列。重申一下,在我看来,MARS只是为汇编程序保留了256 k的全局存储空间,然后在那里启动堆。
我不会将这些解释为数据和堆之间的另一个部分或段。
此外,如果您阅读MARS默认内存配置模型,它会说堆栈(较低)限制与堆基相同,但实际上MARS模拟器不会(或不能)允许堆栈增长到那么大,它会在更高的堆栈位置发出错误,实际限制的大小大约为1或2 MB。