为什么 MARS MIPS 模拟器会抛出 "Load from an Illegal Address" 异常?

Why did the MARS MIPS Simulator throws a "Load from an Illegal Address" exception?

我创建了一个简单的递归 factorial() 函数,它在计算 n * factorial(n-1) 时调用名为 mul_alt() 的递归乘法函数。因此,factorial() 函数执行 return mul_alt(n, factorial(n-1)) 而不是 return n * factorial(n-1)(在 C 表示法中),其中被调用的函数将添加 n + n + ... factorial(n-1) 次。由于 class 的要求,我制作了这个复杂的程序。

该程序在 n <= 9 时工作正常,但是当我尝试 n > 9 时,该程序将 return 在 n = 10 处出现异常,协处理器 0 的值如下:

 (vaddr) = 0x7fbffffc
 (status) = 0x0000ff13
 (cause) = 0x00000014
 (epc) = 0x0040008c

status 寄存器的前两位,我了解到异常处理程序 returned 了一个 ADDRL 异常,这意味着 从非法地址加载。而epc寄存器显示的是导致错误的指令地址,即

0x0040008c: sw $s1, 4($sp)

我的 $sp 寄存器的值为 0x7fbffff8。所以 0x7fbffff8 + 0x4 = 0x7fbffffc(存储在 vaddr 中的值)是 store 指令试图存储 $s1 的内容的地方。关于这种情况,我有几个问题:

  1. 为什么我得到了一个 ADDRL 异常,虽然我实际上使用了存储指令 -- 而不是加载?
  2. 0x7fbffffc能被4整除,那为什么我不能在里面存word大小的数据呢?

我希望我已经表达清楚了我的观点。提前谢谢你。

MIPS 原因 0x14ADDRS 而不是 ADDRL。 ExcCode = 0x14/4 = 5: 地址

这是一个简单的堆栈溢出。 MARS 堆栈可以转到 0x7fc00000,因此允许大约 4M 字节。


// from the default memory configuration menu selection
public static int stackPointer = MemoryConfigurations.getDefaultStackPointer(); //0x7fffeffc;
public static int stackBaseAddress = MemoryConfigurations.getDefaultStackBaseAddress(); //0x7ffffffc;
public static int stackLimitAddress = stackBaseAddress - BLOCK_LENGTH_WORDS * BLOCK_TABLE_LENGTH * WORD_LENGTH_BYTES;
//                          where these constants are 1024, 1024, and 4 respectively

默认值(来自默认内存配置)为 0x7ffffffc (stackBase)、0x7ffffffc (stackPointer)、0x7fc00000 (stackLimitAddress)。

没有用于将堆栈增加 space 超过 4MB 的菜单选项。

有一个内存配置菜单,但它错误地将堆栈限制报告为与所有可用配置的堆基数相同的值。事实并非如此:根据源代码,堆栈限制始终为堆栈基数 - 4MB。

除非您使用sbrk系统调用扩展堆,否则堆基地址和堆栈限制地址之间的内存地址将受到保护。没有进一步扩展堆栈。


另一方面,SPIM 似乎会根据需要扩展堆栈 space,但仅当您修改堆栈指针寄存器时,而不是存储到堆栈指针下方的内存中时。因此在 SPIM 中,如果您将堆栈指针寄存器修改为随机值,即使您将堆栈指针放回加载前的位置,它也会立即无法展开堆栈 space(不进行存储或加载)或相对于该寄存器存储 — 确实是奇怪的行为,但似乎他们特别对待 $sp 寄存器,而不是硬件如何处理它。