If statement 跳转到各种函数MIPS

If statement 跳转到各种函数MIPS,if-statement,assembly,mips,If Statement,Assembly,Mips,所以我是MIPS新手,我想实现简单的模算术函数。我不明白为什么程序没有根据代码中的跳转语句跳转。任何帮助都将不胜感激 .data text_enquiry : .asciiz "Enter operation code (1-add, 2-subtract, 3-multiply, 4-exponentiation, 5-inversion, 6-exit): " text_a : .asciiz "Enter a: " text_b :

所以我是MIPS新手,我想实现简单的模算术函数。我不明白为什么程序没有根据代码中的跳转语句跳转。任何帮助都将不胜感激

    .data
text_enquiry    :   .asciiz "Enter operation code (1-add, 2-subtract, 3-multiply, 4-exponentiation, 5-inversion, 6-exit): "
text_a          :   .asciiz "Enter a: "
text_b          :   .asciiz "Enter b: "
text_m          :   .asciiz "Enter m: "
text_result     :   .asciiz "Result = "
new_line        :   .asciiz "\n"

    .text
main:

    ##  t0 = code, t1 = a, t2 = b, t3 = m

    #print operation message
    la      $a0, text_enquiry
    li      $v0, 4
    syscall

    #read code
    li      $v0, 5
    syscall
    move    $t0, $v0

    #if code == 6
    beq     $t0, 6, exit
    j       rest

exit:
    li      $v0, 10
    syscall

    #else, continue procedure

    #print 'a, b, m' messages and read them
rest:
    la      $a1, text_a
    li      $v0, 4
    syscall
    li      $v0, 5
    syscall
    move    $t1, $v0

    la      $a1, text_b
    li      $v0, 4
    syscall
    li      $v0, 5
    syscall
    move    $t2, $v0

    la      $a1, text_m
    li      $v0, 4
    syscall
    li      $v0, 5
    syscall
    move    $t3, $v0
    j       mod

    ##  t0 = code, t1 = a, t2 = b, t3 = m, t4 = un-modded result, t5 = modded result, t6 = 
mod:
    beq     $t0, 1, func_add
    beq     $t0, 2, func_sub
    beq     $t0, 3, func_mul
    # beq       $t0, 4, func_exp

func_add:
    add     $t4, $t1, $t2
    div     $t4, $t3
    mfhi    $t5
    #print accordingly
    la      $a3, text_result
    li      $v0, 4
    syscall
    move    $a3, $t5
    li      $v0, 1
    syscall
    la      $a3, new_line
    li      $v0, 4
    syscall

    j       main

func_sub:
    sub     $t4, $t1, $t2
    div     $t4, $t3
    mfhi    $t5
    #print accordingly
    la      $a3, text_result
    li      $v0, 4
    syscall
    move    $a3, $t5
    li      $v0, 1
    syscall

    j       main

func_mul:
    mult    $t1, $t2
    mflo    $t4
    div     $t4, $t3
    mfhi    $t5
    #print accordingly
    la      $a3, text_result
    li      $v0, 4
    syscall
    move    $a3, $t5
    li      $v0, 1
    syscall

    j       main
如您所见,当代码为“6”时,代码工作正常,但对任何其他代码值都不起作用

我不明白为什么程序没有根据代码中的跳转语句跳转。任何帮助都将不胜感激

    .data
text_enquiry    :   .asciiz "Enter operation code (1-add, 2-subtract, 3-multiply, 4-exponentiation, 5-inversion, 6-exit): "
text_a          :   .asciiz "Enter a: "
text_b          :   .asciiz "Enter b: "
text_m          :   .asciiz "Enter m: "
text_result     :   .asciiz "Result = "
new_line        :   .asciiz "\n"

    .text
main:

    ##  t0 = code, t1 = a, t2 = b, t3 = m

    #print operation message
    la      $a0, text_enquiry
    li      $v0, 4
    syscall

    #read code
    li      $v0, 5
    syscall
    move    $t0, $v0

    #if code == 6
    beq     $t0, 6, exit
    j       rest

exit:
    li      $v0, 10
    syscall

    #else, continue procedure

    #print 'a, b, m' messages and read them
rest:
    la      $a1, text_a
    li      $v0, 4
    syscall
    li      $v0, 5
    syscall
    move    $t1, $v0

    la      $a1, text_b
    li      $v0, 4
    syscall
    li      $v0, 5
    syscall
    move    $t2, $v0

    la      $a1, text_m
    li      $v0, 4
    syscall
    li      $v0, 5
    syscall
    move    $t3, $v0
    j       mod

    ##  t0 = code, t1 = a, t2 = b, t3 = m, t4 = un-modded result, t5 = modded result, t6 = 
mod:
    beq     $t0, 1, func_add
    beq     $t0, 2, func_sub
    beq     $t0, 3, func_mul
    # beq       $t0, 4, func_exp

func_add:
    add     $t4, $t1, $t2
    div     $t4, $t3
    mfhi    $t5
    #print accordingly
    la      $a3, text_result
    li      $v0, 4
    syscall
    move    $a3, $t5
    li      $v0, 1
    syscall
    la      $a3, new_line
    li      $v0, 4
    syscall

    j       main

func_sub:
    sub     $t4, $t1, $t2
    div     $t4, $t3
    mfhi    $t5
    #print accordingly
    la      $a3, text_result
    li      $v0, 4
    syscall
    move    $a3, $t5
    li      $v0, 1
    syscall

    j       main

func_mul:
    mult    $t1, $t2
    mflo    $t4
    div     $t4, $t3
    mfhi    $t5
    #print accordingly
    la      $a3, text_result
    li      $v0, 4
    syscall
    move    $a3, $t5
    li      $v0, 1
    syscall

    j       main
您的程序正在根据输入进行跳转

您无法看到的是它真正的功能以及进一步文本输出失败的原因,您无法看到,因为您甚至没有查看(在调试器中,单步执行每条指令)

请看一看,您会清楚地看到,例如对于输入“3”,代码将在标签
rest:
之后到达指令,因此分支是正确的

后来的代码没有达到您的预期,因为它没有打印其他帮助程序提示,因为它使用错误的参数调用
syscall
(代码使用字符串地址设置
a1
,而不是
a0
,并且在
a0
中仍然是原始操作提示地址),但它是按计划执行的

通常,仅通过检查输入/输出来决定汇编代码的正确性是非常糟糕的做法,因为您经常“偶然”获得正确的输出,而代码已经在做一些与计划不同的事情,如果您继续扩展代码,或者使用不同的输入,这可能会在以后影响您

为了确定汇编代码是否正确,您应该在编写代码时花相当多的时间在调试器中,验证不同的输入,并思考代码如何工作,以及是否真的按照计划/假设工作——按指令编写

最终的代码应该只包含您确切知道它们在做什么的指令,以及它们为什么是代码的一部分,以及它们为什么被放置在它们所在的位置。如果任何东西在你没有真正理解它的情况下“偶然”工作,你必须修复它(或者通过理解它是如何工作的,或者通过以你理解它是如何工作的方式重写它),它仍然是bug,即使输出是正确的

我不明白为什么程序没有根据代码中的跳转语句跳转。任何帮助都将不胜感激

    .data
text_enquiry    :   .asciiz "Enter operation code (1-add, 2-subtract, 3-multiply, 4-exponentiation, 5-inversion, 6-exit): "
text_a          :   .asciiz "Enter a: "
text_b          :   .asciiz "Enter b: "
text_m          :   .asciiz "Enter m: "
text_result     :   .asciiz "Result = "
new_line        :   .asciiz "\n"

    .text
main:

    ##  t0 = code, t1 = a, t2 = b, t3 = m

    #print operation message
    la      $a0, text_enquiry
    li      $v0, 4
    syscall

    #read code
    li      $v0, 5
    syscall
    move    $t0, $v0

    #if code == 6
    beq     $t0, 6, exit
    j       rest

exit:
    li      $v0, 10
    syscall

    #else, continue procedure

    #print 'a, b, m' messages and read them
rest:
    la      $a1, text_a
    li      $v0, 4
    syscall
    li      $v0, 5
    syscall
    move    $t1, $v0

    la      $a1, text_b
    li      $v0, 4
    syscall
    li      $v0, 5
    syscall
    move    $t2, $v0

    la      $a1, text_m
    li      $v0, 4
    syscall
    li      $v0, 5
    syscall
    move    $t3, $v0
    j       mod

    ##  t0 = code, t1 = a, t2 = b, t3 = m, t4 = un-modded result, t5 = modded result, t6 = 
mod:
    beq     $t0, 1, func_add
    beq     $t0, 2, func_sub
    beq     $t0, 3, func_mul
    # beq       $t0, 4, func_exp

func_add:
    add     $t4, $t1, $t2
    div     $t4, $t3
    mfhi    $t5
    #print accordingly
    la      $a3, text_result
    li      $v0, 4
    syscall
    move    $a3, $t5
    li      $v0, 1
    syscall
    la      $a3, new_line
    li      $v0, 4
    syscall

    j       main

func_sub:
    sub     $t4, $t1, $t2
    div     $t4, $t3
    mfhi    $t5
    #print accordingly
    la      $a3, text_result
    li      $v0, 4
    syscall
    move    $a3, $t5
    li      $v0, 1
    syscall

    j       main

func_mul:
    mult    $t1, $t2
    mflo    $t4
    div     $t4, $t3
    mfhi    $t5
    #print accordingly
    la      $a3, text_result
    li      $v0, 4
    syscall
    move    $a3, $t5
    li      $v0, 1
    syscall

    j       main
您的程序正在根据输入进行跳转

您无法看到的是它真正的功能以及进一步文本输出失败的原因,您无法看到,因为您甚至没有查看(在调试器中,单步执行每条指令)

请看一看,您会清楚地看到,例如对于输入“3”,代码将在标签
rest:
之后到达指令,因此分支是正确的

后来的代码没有达到您的预期,因为它没有打印其他帮助程序提示,因为它使用错误的参数调用
syscall
(代码使用字符串地址设置
a1
,而不是
a0
,并且在
a0
中仍然是原始操作提示地址),但它是按计划执行的

通常,仅通过检查输入/输出来决定汇编代码的正确性是非常糟糕的做法,因为您经常“偶然”获得正确的输出,而代码已经在做一些与计划不同的事情,如果您继续扩展代码,或者使用不同的输入,这可能会在以后影响您

为了确定汇编代码是否正确,您应该在编写代码时花相当多的时间在调试器中,验证不同的输入,并思考代码如何工作,以及是否真的按照计划/假设工作——按指令编写


最终的代码应该只包含您确切知道它们在做什么的指令,以及它们为什么是代码的一部分,以及它们为什么被放置在它们所在的位置。如果您没有真正理解任何东西“偶然”工作,您必须修复它(通过理解它是如何工作的,或者通过以您理解它是如何工作的方式重写它),即使输出是正确的,它仍然是错误。

当您说代码“工作不正常”时,请更具体一些。你说了它不做什么,但没有说它做什么。你使用什么环境来运行它?从退出系统调用来看,我猜是SPIM系列模拟器或火星。这些可以在选项中配置,以模拟延迟分支(像真正的CPU一样)或不模拟延迟分支(对于新手来说更容易理解,但不像真正的MIPS CPU)。此外,这些模拟器还包括调试器,因此您可以轻松地自己尝试,每一条指令都会发生什么,慢慢地跳过它们,检查寄存器中的所有值以及您的假设与前一条指令的实际操作。(我没有费心将您的代码复制到simulator+自己尝试)但我认为第一个分支应该在延迟分支关闭(延迟分支“打开”时工作(6 vs其他值),我实际上不确定延迟分支包含另一条
j
指令时会发生什么,从未在simulator中尝试过,我不是MIPS专家),所以不清楚什么不适合你。我相信标签
rest:
是在非6输入的情况下达到的。@Ped7g“如果分支、跳转、ERET、DERET或WAIT指令被放置在分支或跳转的延迟槽中,则处理器操作是不可预测的。”@Ped7g否,即使是第一个分支也不起作用。它会继续在主部分打印操作消息,而不会进入任何其他部分(如
rest
mod
,等等)。当您说代码“工作不正常”时,请更具体一些。你说了它不做什么,但没有说它做什么。你使用什么环境来运行它?从退出系统调用来看,我猜是SPIM系列模拟器或火星。这些可以在选项中配置,以模拟延迟分支(如