Assembly Case语句代码在Mars模拟器中运行,但在QtSpim中出错

Assembly Case语句代码在Mars模拟器中运行,但在QtSpim中出错,assembly,mips,Assembly,Mips,正如标题所提到的,我已经在Mars MIPS模拟器中编写了这段代码,在那里组装和运行代码工作正常,没有错误。当我将同一个文件带到QtSpim并在那里运行时,会出现以下错误: 似乎QtSpim在我调用CASE的标签地址时遇到了问题,我没有足够的经验来了解原因。这是我的密码: .data jumptable: .word isD, is1, is2, is3, is4 currentvalue: .asciiz "Returned : i = " #Used for result outpu

正如标题所提到的,我已经在Mars MIPS模拟器中编写了这段代码,在那里组装和运行代码工作正常,没有错误。当我将同一个文件带到QtSpim并在那里运行时,会出现以下错误:

似乎QtSpim在我调用
CASE
的标签地址时遇到了问题,我没有足够的经验来了解原因。这是我的密码:

.data
jumptable: .word isD, is1, is2, is3, is4
currentvalue: .asciiz "Returned : i = "     #Used for result output
space: .asciiz " \n"                        #Used for result output

.text
MAIN:
li $a0, 0               #testing use of the argument register toholdinput
jal CASE                #set $ra and go to the case procedure

li $v0, 4               #load syscall 4 to print text
la $a0, currentvalue    #load the string value of currentvalue into $a0
syscall                 #print out currentvalue

li $v0, 1               #load syscall 1 to print integer
move $a0, $t3           #move the contents of $t3 to $a0
syscall                 #print the integer in $a0

li $v0, 10              #load syscall 10 to exit program
syscall                 #exit program


CASE:
    la $t3, ($a0)       #load 'i' into a temporary value since we will be using $a0 for syscalls shortly

    blt $a0, 1, isD     #jump to default if i less than 1
    bgt $a0, 4, isD     #jump to default if i greater than 4

    sll $t0, $a0, 2     #multiplies 'i' by 2^2
    la $t1, jumptable   #load the base address of the jump table into $t1
    add $t1, $t1, $t0   #$t1 = $t1(base address of table) + $t0('i' * 4)
    lw $t2, ($t1)       #$t2 is loaded with the address of label found in $t1
    jr $t2

    is1:
        addi $t3, $t3, 1    #increment 'i' by 1
        jr $ra              #jump back to the return address in main
    is2:
        addi $t3, $t3, 2    #increment 'i' by 2
        jr $ra              #jump back to the return address in main
    is3:
        addi $t3, $t3, 3    #increment 'i' by 3
        jr $ra              #jump back to the return address in main
    is4:
        addi $t3, $t3, 4    #increment 'i' by 4
        jr $ra              #jump back to the return address in main
    isD:
        li $t0, 0           #set 'i' to 0
        jr $ra              #jump back to the return address in main

好吧,我想我已经明白了。(警告:我只有火星)

在错误消息中,错误来自第188行,因此这不是程序的一部分。它是
spim
调用
main
的代码的一部分

要定义
main
函数,它必须是[小写]和全局的:

mars
spim
都没有像上面那样识别您的
MAIN:
。如果
mars
找不到main,它将在
.text
部分的最低地址启动程序<然而,代码>spim只是抱怨而已


更新:


另一方面,如果你有机会的话,我现在正在学习MIPS,根据我的评论,我的代码中的每一件事情都是正确的吗

我做了我版本的代码审查,这意味着我对源代码进行了注释,并对其进行了清理,直到我理解了所发生的事情。对你来说,这只是编辑一些评论。我确实在这个过程中发现了一个小的[一行]错误,我在下面的注释代码中修复了它

你在舞台上的评论做得很好。一些OPs在没有任何评论的情况下发布asm。好的评论[用任何语言]都应该表现出意图。也就是说,您希望您的程序在给定的点上做什么(“什么/为什么”)。实际的asm说明是“如何”

正如您所做的,我建议您对大多数asm说明使用侧边栏注释。我还建议在函数上方添加注释块

我清理了你的评论,就像我自己清理一样,因为其中一些评论如下:

x = 23;  // set the value of x to twenty three
当您学习asm时,有时您必须这样做才能记住给定asm指令的功能。但是,它们可能会妨碍遵循程序的流程/逻辑。因此,我在下面将它们注释为“学习者”[最终,你会删除或缩短你自己],并用我可能会做/建议的内容替换侧栏

另外,假设asm程序员至少熟悉一种高级语言也可以,因此可以使用注释
i<1
i+=3
,等等

为了加快测试速度,我还向
case
中添加了一个参数的用户提示

不管怎样,这里是带注释的源代码[请原谅不必要的样式清理]:

    .data
jumptable:  .word       isD,is1,is2,is3,is4
prompt:     .asciiz     "Enter case input argument: "
currentvalue:   .asciiz "Returned : i = "   # Used for result output
space:      .asciiz     " \n"           # Used for result output

    .text
    .globl  main

main:
    # prompt user for test value
    li      $v0,4                   # syscall: print string
    la      $a0,prompt
    syscall

    # get user test value from stdin
    li      $v0,5                   # syscall: read integer
    syscall
    move    $a0,$v0                 # move to argument for case

    # LEARNER: testing use of the arg reg to hold input
    ###li       $a0,0               # test value for case function

    # LEARNER: set $ra and go to the case procedure (i.e. we are calling the
    # case function)
    jal     case                    # calculate [whatever case calculates ;-)]

    # print the prefix string
    li      $v0,4                   # syscall: print string
    # LEARNER: address of currentvalue into $a0
    la      $a0,currentvalue
    syscall

    # print the value the 'case' function returned
    li      $v0,1                   # syscall: print integer
    # LEARNER: move the contents of $t3 to $a0
    move    $a0,$t3                 # get value to reg for syscall
    syscall

    li      $v0,10                  # syscall: exit program
    syscall

# case -- does what?
#
# RETURNS: what does it return?
#   t3 -- return value
#   FIXME: to follow ABI, this should be v0 but okay for small internal
#   functions like this one.
#
# arguments:
#   a0 -- contains 'i' (FIXME: what is 'i'?)
#
# internal register usage (i.e. what registers get clobbered):
#   t0 -- offset into jump table
#   t1 -- address of jump table
#   t2 -- internal jump address
case:
    move    $t3,$a0                 # save 'i' to our work/return register

    blt     $a0,1,isD               # jump to default if i < 1
    bgt     $a0,4,isD               # jump to default if i > 4

    # LEARNER: multiply 'i' by 2^2 (4) --> i <<= 2
    sll     $t0,$a0,2               # get the offset into the jump table

    la      $t1,jumptable           # base address of the jump table

    # LEARNER: $t1 = $t1(base address of table) + $t0('i' * 4)
    add     $t1,$t1,$t0             # add offset to base address

    # LEARNER: $t2 is loaded with the address of label found in $t1
    lw      $t2,($t1)               # jump_address = jumptable[i]
    jr      $t2                     # jump to desired label

is1:
    addi    $t3,$t3,1               # i += 1
    jr      $ra                     # return to caller

is2:
    addi    $t3,$t3,2               # i += 2
    jr      $ra                     # return to caller

is3:
    addi    $t3,$t3,3               # i += 3
    jr      $ra                     # return to caller

is4:
    addi    $t3,$t3,4               # i += 4
    jr      $ra                     # return to caller

isD:
    # BUG: this should be t3
    ###li       $t0,0               # i = 0
    li      $t3,0                   # i = 0
    jr      $ra                     # return to caller
.data
跳转表:。字isD、is1、is2、is3、is4
提示:.asciiz“输入案例输入参数:”
currentvalue:.asciiz“返回:i=“#用于结果输出
空格:.asciiz“\n”#用于结果输出
.文本
格洛博梅因酒店
主要内容:
#提示用户输入测试值
li$v0,4#系统调用:打印字符串
la$a0,提示
系统调用
#从stdin获取用户测试值
li$v0,5#系统调用:读取整数
系统调用
移动$a0,$v0#移动到案例的参数
#学员:测试使用arg reg来保持输入
###li$a0,0#机箱功能的测试值
#学员:设置$ra并进入案例程序(即,我们调用
#案例功能)
日航案例#计算[任何案例计算;-)]
#打印前缀字符串
li$v0,4#系统调用:打印字符串
#学习者:将currentvalue转换为$a0的地址
la$a0,当前值
系统调用
#打印“case”函数返回的值
li$v0,1#系统调用:打印整数
#学员:将$t3的内容移动到$a0
将$a0、$t3#获取值以注册系统调用
系统调用
li$v0,10#系统调用:退出程序
系统调用
#凯斯,做什么?
#
#返回:返回什么?
#t3——返回值
#修正:为了遵循ABI,这应该是v0,但对于小的内部
#像这样的功能。
#
#论据:
#a0——包含“i”(修正:什么是“i”
#
#内部寄存器使用(即,哪些寄存器被阻塞):
#t0——跳转表中的偏移量
#t1——跳转表的地址
#t2——内部跳转地址
案例:
将$t3、$a0#保存“i”到我们的工作/回报登记簿
blt$a0,1,isD#如果i<1,则跳转为默认值
bgt$a0,4,isD#如果i>4,则跳转到默认值

#学习者:将“i”乘以2^2(4)-->我怀疑SPIM区分大小写,并尝试跳到
main
,而您的代码只定义
main
。哇,请注意,我将main和case分别改为main和case,瞧,我得到了输出。非常感谢。这是有道理的,我刚刚重命名了标签,它在Spim中对我有效,但到重命名时还没有在Mars中尝试过。另一方面,如果你有机会,我现在正在学习MIPS,根据我的评论,我的代码中的每件事看起来都很好吗?非常感谢你。我真的很感激!
x = 23;  // set the value of x to twenty three
    .data
jumptable:  .word       isD,is1,is2,is3,is4
prompt:     .asciiz     "Enter case input argument: "
currentvalue:   .asciiz "Returned : i = "   # Used for result output
space:      .asciiz     " \n"           # Used for result output

    .text
    .globl  main

main:
    # prompt user for test value
    li      $v0,4                   # syscall: print string
    la      $a0,prompt
    syscall

    # get user test value from stdin
    li      $v0,5                   # syscall: read integer
    syscall
    move    $a0,$v0                 # move to argument for case

    # LEARNER: testing use of the arg reg to hold input
    ###li       $a0,0               # test value for case function

    # LEARNER: set $ra and go to the case procedure (i.e. we are calling the
    # case function)
    jal     case                    # calculate [whatever case calculates ;-)]

    # print the prefix string
    li      $v0,4                   # syscall: print string
    # LEARNER: address of currentvalue into $a0
    la      $a0,currentvalue
    syscall

    # print the value the 'case' function returned
    li      $v0,1                   # syscall: print integer
    # LEARNER: move the contents of $t3 to $a0
    move    $a0,$t3                 # get value to reg for syscall
    syscall

    li      $v0,10                  # syscall: exit program
    syscall

# case -- does what?
#
# RETURNS: what does it return?
#   t3 -- return value
#   FIXME: to follow ABI, this should be v0 but okay for small internal
#   functions like this one.
#
# arguments:
#   a0 -- contains 'i' (FIXME: what is 'i'?)
#
# internal register usage (i.e. what registers get clobbered):
#   t0 -- offset into jump table
#   t1 -- address of jump table
#   t2 -- internal jump address
case:
    move    $t3,$a0                 # save 'i' to our work/return register

    blt     $a0,1,isD               # jump to default if i < 1
    bgt     $a0,4,isD               # jump to default if i > 4

    # LEARNER: multiply 'i' by 2^2 (4) --> i <<= 2
    sll     $t0,$a0,2               # get the offset into the jump table

    la      $t1,jumptable           # base address of the jump table

    # LEARNER: $t1 = $t1(base address of table) + $t0('i' * 4)
    add     $t1,$t1,$t0             # add offset to base address

    # LEARNER: $t2 is loaded with the address of label found in $t1
    lw      $t2,($t1)               # jump_address = jumptable[i]
    jr      $t2                     # jump to desired label

is1:
    addi    $t3,$t3,1               # i += 1
    jr      $ra                     # return to caller

is2:
    addi    $t3,$t3,2               # i += 2
    jr      $ra                     # return to caller

is3:
    addi    $t3,$t3,3               # i += 3
    jr      $ra                     # return to caller

is4:
    addi    $t3,$t3,4               # i += 4
    jr      $ra                     # return to caller

isD:
    # BUG: this should be t3
    ###li       $t0,0               # i = 0
    li      $t3,0                   # i = 0
    jr      $ra                     # return to caller