【发布时间】:2023-03-16 17:19:01
【问题描述】:
(我对 Mips 很陌生,我知道我的一些语法和/或逻辑可能看起来很奇怪或不正确。感谢您的理解)。
我被要求从用户那里读取一系列字符串到通过在程序中分配空间创建的数组中。在我的 get_input 函数中,当我使用系统调用 8 读取字符串时,我传递了数组的地址和字符缓冲区大小。
get_input 函数存储输入的字符串,(最多 32 个字符),然后将其传递给 strtrunc 函数以截断字符串末尾的 $zero 值。 strtrunc 函数还计算单词的大小并将值保存到 $v0。
此时,程序返回 get_input 函数并将 $v0 中的值保存到长度数组中,然后增加所用数组的偏移量。
我在存储输入的单词并稍后访问它时遇到了一系列问题 - 最初,我使用四个偏移量作为我的单词数组来存储单词,但是,输入的单词超过了四个字符会将剩余的字符推到下一个偏移量上。
示例(输入感谢):[n a h T][ \0 \0 s k],输入“Again”时的循环与前面的字符重叠:示例(再次输入后):[n a h T][ i a g A] [\0 \0 \0 n] 这就是为什么我为我们在 strtrunc 函数中添加的 $zero 添加了前一个单词大小的偏移量 + 1。
我想这个问题更适合我选择如何将用户输入的字符串保存到数组中。我做错了吗?我稍后应该向后读取输入的字符串,但是,我只能正确读取输入到程序中的第一个字符串。 (我不包括该功能,因为该问题可以很容易地解决)。最后,我可以正确访问长度数组和偏移量为 4 的存储值。这只是我无法正确访问的字符/字符串数组。我希望字符串的地址具有相同的四个偏移量,同时仍然存储整个字符串而不会被以下单词覆盖。
[s k n a h T][n i a g A]
0x0000 0x0004
.data
prompt: .asciiz "Please enter up to 16 strings (max 31 characters) 1 per line\nEnter a blank line to finish inputing the strings.\n"
prompt1: .asciiz "Next string: "
.align 2
strings: .space 512 #16 strings of up to 32 characters each including the null character
.align 2
lengths: .space 64 #Space for 16 values for the length
.text
main:
# Step 1: Read user-inputted strings
la $a0, prompt
li $v0, 4
syscall
#Call get_input
la $a0, prompt1
la $a1, strings
li $a2, 32
jal get_input
# Step 2: Calculate string lengths
#Already done from get_input and stored into the Lengths Array
exit_main:
li $v0, 10 # 10 is the exit program syscall
syscall # execute call
###############################################################
# Grabs the inputted strings and saves to strings array.
#$a0 - address of prompt to print
#$a1 - address to store string
#$a2 - Max string length
#$s0 - Loop counter
#$t3 - Offset to store information
#$t4 - Load the byte for exit loop
#$t5 - Lengths Array Offset
get_input:
subi $sp, $sp, 4 #Push return address onto the stack to save it
sw $ra, ($sp)
li $s0, 0 #initalize counter variable
li $t3, 0 #initalize offset variable
li $t5, 0 #Initalize offset variable
get_input_loop:
beq $s0, 16, end_get_input #Loop statement check
la $a0, prompt1
li $v0, 4 #Syscall for prompt text
syscall
la $a0, strings($t3) #$a1 has the location to store the string, move that into $a0 for the read word syscall
move $a1, $a2 #$a2 has the maximum character buffer, move that into $a1 for the read word syscall
li $v0, 8
syscall
#$a0 now has the inputted word—We want to manipulate. Trucnate and then store the word inside of the array.
lbu $t4, ($a0) #Check to see if the inputted word is null or just a space
beq $t4, $zero, end_get_input #If so, exit loop
#Trunc the string
jal strtrunc
beq $t4, 0x20, end_get_input #If the inputted byte is a space, exit the loop
#At this point $v0 has the length of the string and the truncatted string has been saved
sw $v0, lengths($t5) #Store the length found in $v0 to lengths
addi $t5, $t5, 4 #Add 4 to the lengths offest
add $t3, $t3, $v0 #Add whatever the length of the last string was to the word offest
addi $t3, $t3, 1 #Add one more for the $zero we added in the strtrunc function
addi $s0, $s0, 1 #Add one to the total count of the strings array
j get_input_loop
end_get_input:
lw $ra, 0($sp)
addi $sp, $sp, 4
jr $ra
###############################################################
#Truncate string at newline character.
#$a0 - address of string
#Returns
#$v0 - Length of string
strtrunc:
move $t0, $zero
move $t1, $a0
str_loop:
lbu $t2, ($t1) #Character at a spot in the word
beq $t2, 0x20 end_strtrunc #If the byte is a space
beq $t2, 0xA end_strtrunc
beq $t2, 0x0 end_strtrunc
addi $t0, $t0, 1 #Length of string
addi $t1, $t1, 1 #Byte offset
j str_loop
end_strtrunc:
sb $zero, ($t1)
move $v0, $t0
jr $ra
【问题讨论】:
-
您将所有字符串打包到字符串空间中。因此,要访问第二个字符串,您必须添加第一个字符串的长度(+1 表示 null),要访问第三个字符串,您必须知道第二个字符串的地址并添加其长度 +1,或从第一个开始,并添加第一个字符串的长度和第二个字符串的长度(+nulls)。
-
但是
jal get_input之后没有显示任何代码,那么您的问题是什么? -
与字符数据分开,您可以存储一个指向每个字符串开头的指针数组,以便您可以随机索引到它。赞 C
char *argv[]
标签: arrays string assembly mips