首页 > 解决方案 > 为什么 MARS MIPS 模拟器会抛出“从非法地址加载”异常?

问题描述

我创建了一个简单的递归factorial()函数,该函数调用递归乘法函数,mul_alt()只要它求值就被调用n * factorial(n-1)。因此,函数执行而不是return n * factorial(n-1)(在 C 表示法中),被调用的函数将在其中添加时间。我制作了这个复杂的程序,因为我的班级要求如此。factorial()return mul_alt(n, factorial(n-1))n + n + ... factorial(n-1)

该程序适用于 n <= 9,但是当我尝试时n > 9,该程序将返回一个异常,n = 10协处理器 0 的值如下:

$8 (vaddr) = 0x7fbffffc
$12 (status) = 0x0000ff13
$13 (cause) = 0x00000014
$14 (epc) = 0x0040008c

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

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

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

  1. ADDRL尽管我实际上使用了存储指令,但为什么会出现异常——而不是加载?
  2. 0x7fbffffc可以被 4 整除,为什么我不能在其中存储字大小的数据?

我希望我已经清楚地表达了我的观点。先感谢您。

标签: mipsmars-simulator

解决方案


MIPS原因0x14不是. ExcCode = 0x14/4 = 5:地址ADDRSADDRL

这是一个简单的堆栈溢出。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)、0x7fffeffc (stackPointer)、0x7fc00000 (stackLimitAddress)。

没有菜单选项可以将堆栈空间增加到 4MB 以上。

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

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


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


推荐阅读