我正在尝试在MIPS中实现puts
。我使用了$a0
。它从该寄存器的地址开始打印字符串。但是,我现在正在尝试为任意数量的字符串实现puts
,这意味着我不能再使用寄存器了。我很困惑如何有效地使用堆栈。从我的主程序,我堆叠任意数量的字符串。然后,我想要jal
到puts
,这将打印所有字符串。我还在堆栈顶部传递要打印的字符串数。
以下是puts
的代码:
# puts - prints ASCII to the screen
# prints from $a0, $a1, $a2, $a3 (buffers)
# stops when chracter is NULL
# ASSUME THAT WHEN PUTS IS CALLED, AT LEAST ONE STRING IS PASSED
#
# CALLING CONVENTION
#
# I decided not to use any of the registers $a0-$a4.
# Instead, the caller stacks all the strings it wants to print in the stack.
# On top of it, it adds the number of strings it wants to print.
# puts will loop, printing each string, until it has printed all of them.
#
# Since the caller is using "s" registers, puts must save them to the stack.
# Thus, these will be put on top of the stack.
# puts will have to access the strings below the stacked registers.
#
# ============ STACK DIAGRAM ==============
#
# \ Number of Strings \ TOP
# \ String 1 \ +200
# \ String 2 \ +400
# \ String 3 \ +600
# \ String 4 \ +800
# \ String 5 \ +/000
# \ String 6 \ +...
# \ ... \
#
# on entry:
# $ra -- return address
# 0($sp) -- number of strings to print
# x($sp) -- strings to print
#
# on exit:
# $v0 -- number of character printed
#
.text
puts:
addi $sp, $sp, -20 # make room for 6 registers
sw $ra, 16($sp) # save $ra on the stack
sw $s0, 12($sp) # save $s0 on the stack
sw, $s1, 8($sp) # save $s1 on the stack
sw, $s2, 4($sp) # save $s2 on the stack
sw, $s3, 0($sp) # save $s3 on the stack
lw $s0, 224($sp) # copy address of first string inside $s0
lw $s1, 24($sp) # copy number of strings to print inside $s1
move $s2, $zero # counter for the number of strings printed
move $s3, $zero # counter for the number of characters sent to putchar
putsString:
** lbu $t3, ($s0) # load ccurrent char into #t3
beq $t3, $zero, exitString # exit puts if the current character is the NULL character
move $a0, $t3 # put the character to print inside $a0, accessible by putchar
jal putchar # print char using putchar
addi $s3, $s3, 1 # character count += 1
addi $s0, $s0, 4 # increment string address by 1 word (4 bytes)
j putsString # Loop to print next character
exitString:
addi $s2, $s2, 1 # increment number of strings printed
beq $s1, $s2, exitPuts # if # of strings to print = # of strings printed, then exit puts; else, increment # of strings printed
addi $s0, $s0, 200 # $s0 now points to next string to print
j putsString
exitPuts:
move $v0, $s4 # return number of character printed
lw $s3, 0($sp) # restore stack
lw $s2, 4($sp) # -
lw $s1, 8($sp) # -
lw $s0, 12($sp) # -
lw $ra, 16($sp) # -
addi $sp, $sp, 20 # pop from stack
jr $ra # return
带有**的线路现在是错误的线路。我得到Runtime exception at 0x00400124: address out of range 0x00000000
。
以下是我如何将字符串保存到堆栈中(我现在用gets
读取2(2是硬编码的)字符串。
init:
beq $s0,2,continue
move $a0, $s2 # load buffer address into $a0
la $t1, limit # - load limit into $a1
lb $a1, ($t1) # - ...
jal gets # call gets - it will modify buffer
move $t0, $v0 # $t0 = string count returned by gets
moveBufferToStack:
lbu $t1, ($s2) # get first character inside buffer
beqz $t1, endMoveBuffer
sw $t1, ($sp) # copy buffer(i) into array(i)
addi $sp, $sp, 4 # array pointer points a position forward
addi $s2, $s2, 4 # same for array pointer
j moveBufferToStack
endMoveBuffer:
addi $sp, $sp, 200 # step to next array cell
addi $s0, $s0, 1 # increment number of strings read
j init # loop until we have 9 elements
continue:
jal puts
j done
答案 0 :(得分:2)
只关注问题,我看到了:
lw $s0, 224($sp) # copy address of first string inside $s0
...
putsString:
lbu $t3, ($s0) # load ccurrent char into #t3
所以你已经加载$s0
,内存的内容从$sp
开始经过224个字节。如果我理解正确,那就是字符串的前四个字节。意思是,如果字符串是“Madam,我是Adam”,那么$s0
包含'a''d'''M'(如果我的字节顺序正确的话)。
因此,当您执行lbu $t3, ($s0)
时,您未将当前字符加载到$t3
。您正在加载 $s0
指向的字节,它将成为内存中的随机点。如果您的字符串为空,$s0
可能包含0x00000000 - 因此会产生您收到的错误。
我认为您想要做的是lw
,而不是addi $s0, $sp, 224
。{{1}}。然后,$ s0将指向$ sp + 224的地址。