为什么火星MIPS模拟器会抛出一个;“从非法地址加载”;例外?

为什么火星MIPS模拟器会抛出一个;“从非法地址加载”;例外?,mips,mars-simulator,Mips,Mars Simulator,我创建了一个简单的递归factorial()函数,每当它计算n*factorial(n-1)时,它都会调用一个名为mul\u alt()的递归乘法函数。因此,factorial()函数执行returnmul_alt(n,factorial(n-1)),而不是returnn*factorial(n-1),其中被调用的函数将添加n+n+…factorial(n-1)次。我做了这个复杂的程序,因为我的班级要求如此 该程序在n 9下运行正常,程序将在n=10处返回异常,协处理器0的值如下: $8 (va

我创建了一个简单的递归
factorial()
函数,每当它计算
n*factorial(n-1)
时,它都会调用一个名为
mul\u alt()
的递归乘法函数。因此,
factorial()
函数执行
returnmul_alt(n,factorial(n-1))
,而不是
returnn*factorial(n-1)
,其中被调用的函数将添加
n+n+…
factorial(n-1)
次。我做了这个复杂的程序,因为我的班级要求如此

该程序在n 9下运行正常,程序将在
n=10
处返回异常,协处理器0的值如下:

$8 (vaddr) = 0x7fbffffc
$12 (status) = 0x0000ff13
$13 (cause) = 0x00000014
$14 (epc) = 0x0040008c
状态
寄存器的前两位,我了解到异常处理程序返回了
ADDRL
异常,这意味着从非法地址加载。并且
epc
寄存器显示导致错误的指令的地址,即

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

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

  • 为什么我得到了一个
    ADDRL
    异常,尽管我实际上使用了一个存储指令——notload
  • 0x7fbffffc
    可以被4整除,那么为什么不允许我在其中存储字大小的数据呢

  • 我希望我已经把我的观点说清楚了。提前感谢。

    MIPS cause
    0x14
    是一个
    ADDRS
    而不是
    ADDRL
    。ExcCode=0x14/4=5:地址

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


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

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

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

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



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

    我明白了,我认为错误是在
    状态
    寄存器中读取的。谢谢。嘿,伙计,你知道为什么当我试图在内存地址中执行
    sw
    指令时,MARS返回“地址超出范围0x7fbffffc”吗?我意识到当我在地址
    尝试
    sw
    时,它在MARS的源代码中被硬编码为4MB。见我的编辑上面。
    // 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