在MIPS1编译时如何确定静态数据变量地址?

时间:2019-05-28 20:49:44

标签: assembly memory static operating-system mips

因此,在MIPS中,静态变量在.data节中声明,并将它们放置在静态段的内存中。但是,汇编程序是在编译时确定这些地址,还是由操作系统将程序加载到内存中时确定这些地址?

1 个答案:

答案 0 :(得分:1)

  

但是,汇编程序是在编译时确定这些地址,还是在操作系统将程序加载到int内存时确定这些地址?

这取决于操作系统,甚至取决于变量的类型:

10年前,大多数WLAN路由器都使用在其上运行 Linux 的MIPS CPU。

在Linux上,存在一种代码类型,称为“ 与位置有关”代码。这意味着代码将始终被加载到内存中的相同地址。在这种情况下,编译器工具链中的一个工具(编译器,汇编器,链接器...)(*)计算变量的地址并“正确”编写代码。示例:如果变量位于地址0x100024,则代码​​将如下所示:

lui t2, 0x10
lw  t3, 0x24(t2)

然后有“ 位置无关”代码。这种类型的代码可以加载到任何地址。假定变量存储在地址X处,并且标签“ nextAddress”位于地址Y。地址X和Y可能会更改,但是差(X-Y)是固定的。假设X-Y = 0x100024:

  bgezal zero, nextAddress
  nop
nextAddress:
  ; Now the address "nextAddress" is in register "ra"
  lui    t2, 0x10
  addu   t2, t2, ra
  ; The next instruction will access address X+0x100024
  lw     t3, 0x24(t2)

当然,差异(X-Y)是由编译器工具链中的一个工具在编译时计算的。

也有在MIPS CPU上运行 Windows CE 的手持设备(类似于今天的智能手机)。

此操作系统使用所谓的“基本重定位表”:.EXE或.DLL文件包含“所需”地址。文件中的代码看起来像上述的“位置相关”代码。将文件加载到“所需”地址后,无需执行任何操作。

基本重定位表”包含有关文件中地址的信息。例如,文件中所有lui指令的列表。假设用于加载文件的“所需”地址为0x80000,但是Windows必须将文件加载至地址0xA0000。这意味着文件中所有变量的地址都会更改0x20000。 Windows将处理“基本重定位表”中的信息,并将0x20添加到文件中每个lui指令的最后16位,因此在“位置”示例中,lui t2, 0x10变为lui t2, 0x30依赖代码”。

因此,变量的地址首先由编译器工具链计算,但随后由操作系统进行修改。

下一个可能性是“ 全局偏移表”(Linux)和“ 导入表”(Windows)。这些通常用于访问DLL文件中的变量。

全局偏移量表包含实际变量的地址。在C编程语言中,可以通过以下方式对此进行解释:

实际的C代码:

static int staticVariable;
...
staticVariable = 1234;

生成的汇编代码实际执行的操作:

static int staticVariable;
static int * staticVariable_got = &staticVariable;
...
(*staticVariable_got) = 1234;

组装代码:

lui t2, 0x10
lw  t3, 0x24(t2)
; Now t3 contains the address of the variable
sw  t4, (t3)

在这种情况下,编译器工具链将计算辅助“变量”(staticVariable_got)的地址。但是,实际变量(staticVariable)的地址仅是OS已知的。操作系统将该地址写入“变量” staticVariable_got


(*)注意,这不一定是链接程序;还有一些直接编写可执行文件的编译器(不需要汇编器或链接器),还有一些链接器的输出由其他工具进行后处理。