【问题标题】:On the allocation of static data in the MIPS architectureMIPS架构中静态数据的分配
【发布时间】:2022-01-05 19:38:01
【问题描述】:

在讨论 32 位 MIPS 架构时,Patterson--Hennessy 解释说,静态数据段从0x 1000 0000 开始,以0x 1000 FFFF 结束,全局指针$gp 默认设置为中间地址@987654324 @。据说堆是下一个,因此应该从0x 1001 0000开始。

一些使用 MARS 的实验告诉我,中间有一个附加段,从0x 1001 00000x 1003 FFFF,因此堆只从0x 1004 0000 开始。事实上,当我使用系统调用在堆上存储一个数组时,这个数组将存储在0x 1004 0000 之后。

当我在程序的.data 标头下初始化数据时,似乎会用到这个附加段。这让我很困惑,因为我期望在 .data 下初始化的数据被认为是静态的,因此应该存储在由全局指针控制的段中。

问题。行为是否符合 MARS 标准?如果是,这个位于静态数据和堆之间的附加数据段与位于它前面的静态数据段有何不同?

【问题讨论】:

    标签: assembly global-variables mips heap-memory cpu-architecture


    【解决方案1】:

    你不能太认真地对待这些模拟器。

    我没有理由知道为什么你不能在内存中移动东西。链接器需要知道全局数据符号的位置,以便它可以进行重定位,否则,处理器并不关心。

    为了说明,MARS 在设置中有一个内存配置选项,因此,例如,您可以将模拟器设置为具有有限内存(如 64k)的嵌入式处理器。


    在真实系统上,全局数据将由操作系统程序加载器从程序可执行文件中加载,数据部分将扩大.bss 数量(最初为零)。然后,通常,堆将从下一页边界开始。

    模拟器不做这些细节——它为所有程序使用一个固定的内存模型;因此,例如,它不会像实际系统那样根据程序集中全局变量的实际数量重新调整堆起始位置。

    因此,在我看来,它只是保留 256k 的全局存储空间供汇编程序使用。

    前 64k 保留用于使用 $gp 直接访问,但 MARS 默认情况下不会将任何全局数据放在那里,如果您强制数据从 0x10000000 开始(通过 .data 0x10000000),您可以放置​​符号在那里,但是在 label 位于 $gp 的 16 位范围内的 lw $t0, label($gp) 被视为伪指令(扩展为 3 条指令),它将 label 的绝对值添加到 $gp 中的内容和然后是lw - 这将无法正确访问该全局数据,b/c $gp 持有 0x10008000,因此最终将添加两个指针,而它应该添加 label 相对于 $gp 的偏移量.如果真的想使用$gp(使用默认内存配置模型)通过正确的1指令序列使用全局数据,您可以使用.eqv定义常量而不是定义标签,并自己管理偏移量(yuk,但是将适用于小程序)。

    相反,MARS 将 .data 的默认起始位置设置为 0x10010000,我认为这只是避免了 64k $gp 可访问区域。任何使用数据标签的指令都被扩展为使用以lui 开头的多指令序列。

    重申一下,在我看来,MARS 只是保留 256k 的全局存储空间供汇编程序使用,然后从那里开始堆。

    我不会将其中任何一个解释为数据和堆之间的另一个部分或段。

    另外,如果您阅读 MARS 默认内存配置模型,它会说堆栈(下限)限制与堆基数相同,但实际上 MARS 模拟器不会(或不能)实际允许堆栈增长这么大,它会在更高的堆栈位置发出错误,真正的限制是 1 或 2 MB 大小。

    【讨论】:

    • 谢谢。我同意所有这些内存位置都可以在模拟器中自定义。但是默认设置给我的印象是关于这个额外的数据段有一个我不知道的 MIPS 约定。你同意事实并非如此吗?
    • 请看我的更新。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-14
    • 2017-04-25
    • 2012-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多