mips - 为什么 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
. 关于这种情况,我有几个问题:
ADDRL
尽管我实际上使用了存储指令,但为什么会出现异常——而不是加载?0x7fbffffc
可以被 4 整除,为什么我不能在其中存储字大小的数据?
我希望我已经清楚地表达了我的观点。先感谢您。
解决方案
MIPS原因0x14
不是. ExcCode = 0x14/4 = 5:地址ADDRS
ADDRL
这是一个简单的堆栈溢出。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
特别对待寄存器,而不是硬件如何做。
推荐阅读
- angular - 如何将道具传递给 ng-content?
- r - 为什么for循环中的分组功能不起作用?
- sed - 为以另一个模式开头的每一行替换一个模式
- python - Mathplotlib 根据对象 ID 设置绘图颜色
- go-gorm - ERR:使用结构查询时where子句中的未知列
- c++ - 连接到 Internet 时由 Windows 发送的事件
- api - 在 RxJs 中获取更多数据
- php - phppresentation溢出表问题
- neo4j - 为标签/关系添加描述或评论
- wolfram-mathematica - 在 Mathematica 中为 ListStreamPlot 创建数据