Assembly Case语句代码在Mars模拟器中运行,但在QtSpim中出错
正如标题所提到的,我已经在Mars MIPS模拟器中编写了这段代码,在那里组装和运行代码工作正常,没有错误。当我将同一个文件带到QtSpim并在那里运行时,会出现以下错误: 似乎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
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