关于MIPS架构中静态数据的分配
On the allocation of static data in the MIPS architecture
在讨论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
开始。实际上,当我使用系统调用在堆上存储数组时,该数组将存储在 0x 1004 0000
之后。
当我在程序的 .data
header 下初始化数据时,似乎使用了这个额外的段。这让我感到困惑,因为我期望在 .data
下初始化的数据被认为是静态的,因此应该存储在由全局指针控制的段中。
问题。该行为是否符合 MARS 标准?如果是,这个位于静态数据和堆之间的附加数据段与位于它前面的静态数据段有何不同?
你不能对这些模拟器太认真。
我不知道为什么不能在内存中移动内容。链接器需要知道全局数据符号的位置,以便它可以进行重定位,否则,处理器不关心。
为了说明,MARS 在“设置”中有一个“内存配置”选项,因此,例如,您可以将模拟器设置为一个具有有限内存(如 64k)的嵌入式处理器。
在真实系统中,全局数据将由操作系统程序加载器从程序可执行文件中加载,并且数据部分将被放大.bss
量(初始为零)。然后,通常,堆将从下一个页面边界开始。
模拟器不做这些细节——它为所有程序使用固定的内存模型;因此,例如,它不会像真实系统那样根据程序集中全局变量的实际数量重新调整堆起始位置。
所以,在我看来,它只是预留256k作为全局存储空间,供汇编程序使用。
前 64k 保留用于使用 $gp
直接访问,但默认情况下 MARS 不会在那里放置任何全局数据,如果您强制数据从 0x10000000 开始(通过 .data 0x10000000
),你可以把符号放在那里,但是做 lw $t0, label($gp)
where label
resides within 16-bit reach of $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。
在讨论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
开始。实际上,当我使用系统调用在堆上存储数组时,该数组将存储在 0x 1004 0000
之后。
当我在程序的 .data
header 下初始化数据时,似乎使用了这个额外的段。这让我感到困惑,因为我期望在 .data
下初始化的数据被认为是静态的,因此应该存储在由全局指针控制的段中。
问题。该行为是否符合 MARS 标准?如果是,这个位于静态数据和堆之间的附加数据段与位于它前面的静态数据段有何不同?
你不能对这些模拟器太认真。
我不知道为什么不能在内存中移动内容。链接器需要知道全局数据符号的位置,以便它可以进行重定位,否则,处理器不关心。
为了说明,MARS 在“设置”中有一个“内存配置”选项,因此,例如,您可以将模拟器设置为一个具有有限内存(如 64k)的嵌入式处理器。
在真实系统中,全局数据将由操作系统程序加载器从程序可执行文件中加载,并且数据部分将被放大.bss
量(初始为零)。然后,通常,堆将从下一个页面边界开始。
模拟器不做这些细节——它为所有程序使用固定的内存模型;因此,例如,它不会像真实系统那样根据程序集中全局变量的实际数量重新调整堆起始位置。
所以,在我看来,它只是预留256k作为全局存储空间,供汇编程序使用。
前 64k 保留用于使用 $gp
直接访问,但默认情况下 MARS 不会在那里放置任何全局数据,如果您强制数据从 0x10000000 开始(通过 .data 0x10000000
),你可以把符号放在那里,但是做 lw $t0, label($gp)
where label
resides within 16-bit reach of $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。