MIPS:合法地将两个连续的“加载字”指令放入同一个寄存器中?

时间:2014-01-22 22:21:53

标签: mips

背景:我们在函数foo(int *p)中看到非常间歇性的崩溃。在解除引用p时发生崩溃,在这些情况下,其值为0xffffffff。对核心转储的分析表明,从以下程序集片段中调用foo()

bne ... somewhere else
lw $a0,44(sp)
lw $a0,40(sp)
jal foo()
lui s1, 0x1000

检查核心转储中的内存显示44(sp)0xffffffff,而40(sp)是我们打算取消引用的正确值。但是,a0内部foo()的值0xfffffffffoo()。 (重要的是要注意,在这种情况下foo()只是访问一个成员;所以它实际上是a0中已经尝试通过ra访问并崩溃的第一条指令。此外, s1指向上述代码段后面的说明,而0x10000000目前包含foo(),因此我们非常确信lw确实来自上述代码段。)

目前我们唯一的理论是连续两个a0jal foo()是一个危险 - 要么是一个记录的,在这种情况下,这看起来像编译器错误;或者没有证件的。

那么:以上大会合法吗?如果是的话,还有其他关于可能发生什么的想法吗?

谢谢!

更新:好吧,事实证明这是一场疯狂的追逐:一位同事对coredump的重复分析在我错过的代码中找到了一条路径,那里有一个跳跃在将a0设置为44(sp)后立即直接指向{{1}}指令。换句话说,代码中有一条路径与我们看到的不涉及危险的结果一致,或“跳过指令”或任何东西......我以为我检查了这个,但我想我要么没有' t,或者错过了...... :(

无论如何,我接受了markgz的回答,因为它回答了我关于这些指令合法性的原始问题(显然它们是)。

1 个答案:

答案 0 :(得分:1)

快速搜索MIPS32R2 ISA的MIPS文档并未在LW指令后对LW显示任何限制。

可能是您CPU中MIPS实现的错误。需要注意的事项包括:

  • 44(sp),40(sp)是什么地址 - 它们是页面边界还是256MByte边界,还是其他有趣的地址?
  • 是否有任何一个负载触发了页面错误?
  • 修补二进制文件以在加载项之间插入NOPSSNOPSYNC指令会导致问题消失吗?