mips-g++-5.4 列表 bnez 跳过 div 指令

mips-g++-5.4 listing bnez skips div instruction

我试图理解为什么 mips-g++ 编译一个简单的 division 子例程,它在其中跳过带有 bnez v0, <jmp> 的实际 div 指令([=14 的伪指令) =]).我的理解是,如果 divisor 为零,则跳过 div 并在这种情况下捕获或中断是有意义的。如果 divisor 不为零,为什么要分支?

我想了解我所缺少的。

子程序

void do_div(int &a, int &b, int &result){
    result = a/b;
}

汇编列表:

(编译器标志:-O0)

00000000 <_Z6do_divRiS_S_>:
   0:   27bdfff8    addiu   sp,sp,-8
   4:   afbe0004    sw  s8,4(sp)
   8:   03a0f025    move    s8,sp
   c:   afc40008    sw  a0,8(s8)
  10:   afc5000c    sw  a1,12(s8)
  14:   afc60010    sw  a2,16(s8)
  18:   8fc20008    lw  v0,8(s8)
  1c:   00000000    nop
  20:   8c430000    lw  v1,0(v0)
  24:   8fc2000c    lw  v0,12(s8)
  28:   00000000    nop
  2c:   8c420000    lw  v0,0(v0)
  30:   00000000    nop
  34:   14400002    bnez    v0,40 <_Z6do_divRiS_S_+0x40>
  38:   0062001a    div zero,v1,v0
  3c:   0007000d    break   0x7
  40:   00001010    mfhi    v0
  44:   00001812    mflo    v1
  48:   8fc20010    lw  v0,16(s8)
  4c:   00000000    nop
  50:   ac430000    sw  v1,0(v0)
  54:   00000000    nop
  58:   03c0e825    move    sp,s8
  5c:   8fbe0004    lw  s8,4(sp)
  60:   27bd0008    addiu   sp,sp,8
  64:   03e00008    jr  ra
  68:   00000000    nop

正如@EOF 在评论中提到的,MIPS 有分支延迟槽的概念。

这是来自BNE(强调我的)的描述:

If the contents of GPR rs and GPR rt are not equal, branch to the effective target address after the instruction in the delay slot is executed.

所以 DIV 总是被执行。您可能会想 “嗯,如果 $v0 为 0,那不是个问题吗?”。但是 DIV 的描述说:

No arithmetic exception occurs under any circumstances.

If the divisor in GPR rt is zero, the arithmetic result value is UNPREDICTABLE.

因此,在除数为零的情况下,您最终会得到不可预测的结果,我们无论如何都不会使用它,因为接下来要做的是使用 BREAK 指令触发断点异常.

来源:面向程序员的 MIPS32™ 架构第 II 卷:MIPS32™ 指令集