【问题标题】:MIPS: Using the stackMIPS:使用堆栈
【发布时间】:2013-02-02 23:03:39
【问题描述】:

我正在阅读 MIPS 手册: “请注意,我们使用“添加立即数”指令的“无符号”版本,因为我们正在处理一个地址,它是一个无符号二进制数。我们不想仅仅因为计算的地址越过中间值而产生异常-内存空间的点。”

这到底是什么意思?特别是跨越内存空间的中点。

而且,在下面的代码中,我不明白为什么它会从 8($sp) 跳到 20($sp)。代码稍后从 12($sp) 和 16($sp) 加载,但是何时对这些内存部分进行处理。我在 jal JILL 中认为可能,但没有给出太多解释。

addiu $sp, $sp, -24 
sw $t1, 0($sp) 
sw $t2, 4($sp) 
sw $t3, 8($sp) 
sw $ra, 20($sp) 
jal JILL
lw $ra, 20($sp) 
lw $t4, 12($sp) 
lw $t5, 16($sp) 
addiu $sp, $sp, 24

【问题讨论】:

  • 这不是“无符号加法”,它是带有“无符号溢出异常”的加法。加法运算本身不知道位的解释。

标签: assembly stack mips


【解决方案1】:

假设 MIPS32 架构具有 32 位地址空间,内存空间的中点将是地址 0x80000000(即 2^31)。 在 32 位有符号(A2-compliment)算术中,从 0 到 0x7FFFFFFF 的整数保留给正数,而从 0x80000000 到 0xFFFFFFFF 的整数保留给负数。

当您发出带符号的加法时,如果加法的结果“越过”该中点,则会出现溢出异常。但是在您的示例中,您实际上是在处理内存地址,而不是有符号数字......因此地址的符号(解释为 32 位数字)是没有意义的,因此您应该使用无符号加法。

关于您的第二个问题,您必须查看 JILL 程序以了解它的作用......该程序肯定会在 12($sp)16($sp) 中存储一些信息

【讨论】:

  • 所以如果我理解正确的话,这只是为了防止由于二进制补码加法而可能发生的溢出异常。还有关于第二个问题,上面的实现和在 JILL 中调整堆栈有什么区别?在代码和概念上会更困难吗?
  • 是的,只是为了防止堆栈位于内存空间中点附近时可能出现的溢出异常。关于您的第二个问题,这完全取决于用于调用其他程序的调用约定。在您的示例中,调用者在堆栈中为被调用过程保留空间以存储结果,然后在从调用者返回时,您的程序使用结果并释放使用的堆栈空间。您不能轻易地将该行为移至 JILL 过程,因为调用者需要保留一些寄存器($t1、$t2、$t3 和 $ra)
  • 我的意思是你不能轻易恢复被调用者中调用者使用的堆栈,因为通常你不知道被调用者是谁。因此,您如何知道要恢复哪些寄存器以及要从堆栈中释放多少内存?答案是你通常不会知道,所以最好遵守这样一个规则,即从堆栈分配空间(并在其中备份信息)的过程是释放它(并恢复需要备份的内容)的过程)
猜你喜欢
  • 2019-09-27
  • 1970-01-01
  • 2017-02-04
  • 1970-01-01
  • 2015-02-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多