MIPS汇编字母统计程序:空格与换行无法输出问题排查
问题分析与修复
问题根源
数组越界写入破坏字符串常量
统计循环中,beq $t5, 104, reset的判断放在了sw $s0, array($t5)之后。array是26个word(共104字节),合法偏移范围是0~100(25*4)。当$t5等于104时,执行sw会把数据写到数组之外的内存区域,恰好覆盖了space和nLine这两个字符串常量的内容,导致打印空格和换行时输出空字符串。字符串结束判断错误
原代码用换行符(ASCII 10)判断字符串结束,但string是.asciiz定义的,结尾是null字符(ASCII 0),所以beq $t2, $t3, nArray永远不会触发,统计循环只能靠数组偏移达到104来终止,进一步加剧了越界问题。
修复步骤
- 调整统计循环的判断顺序
将beq $t5, 104, reset移到sw $s0, array($t5)之前,避免数组越界写入。 - 修正字符串结束符判断
将li $t3, 10改为li $t3, 0,用null字符判断字符串结束。
修复后的代码
.data array: .word 0:26 space: .asciiz " " nLine: .asciiz "\n" string: .asciiz "abbcccddddeffggghhhhijjkkkllllmnnoooppppqrrsssttttuvvwwwxxxxyzz" bye: .ascii "\n**** Thank you for running my program ****\n" .asciiz "\n**************** Goodbye *****************" .text main: addi $t0, $zero, 0 # clear $t0 li $t3, 0 # 0 is ASCII for null terminator (string end) li $t4, 97 # 97 is ASCII for 'a' li $s0, 0 # counter for number occurence li $t5, 0 # initiate counter for array position la $t1, string # load address of string into $t1 count: beq $t5, 104, reset # 先判断是否越界,再执行存储 sw $s0, array($t5) # store letter count in array at position $t5 lb $t2, ($t1) # load next character of string beq $t2, $t3, nArray # once end of string is reached move to next array element beq $t2, $t4, inc # if letter matches, increment count addi $t1, $t1, 1 # if letter does not match, move to next character in string j count # loop inc: addi $s0, $s0, 1 # increment count addi $t1, $t1, 1 # next character in string j count # loop nArray: addi $s0, $zero, 0 # clear $s0 la $t1, string # load address of string into $t1 addi $t4, $t4, 1 # move to next ASCII letter addi $t5, $t5, 4 # move to next array element j count # loop reset: addi $t0, $zero, 0 # clear $t0 addi $t1, $zero, 0 # clear $t1 addi $t2, $zero, 0 # clear $t2 addi $t3, $zero, 0 # clear $t3 addi $t4, $zero, 0 # clear $t4 addi $t5, $zero, 0 # clear $t5 addi $t6, $zero, 0 # clear $t6 printA1: beq $t0, 104, done # once through 26 words, end beq $t0, 52, printNl # once through 13 words, print new line printA2: lw $t6, array($t0) # load next array element addi $t0, $t0, 4 # increment array position li $v0, 1 # load syscall code for print_int move $a0, $t6 # move array element value into syscall argument syscall # print integer li $v0, 4 # load syscall code for print_string la $a0, space # load space into syscall argument syscall # print space j printA1 # loop printNl: li $v0, 4 # load syscall code for print_string la $a0, nLine # load new line into argument for syscall syscall # print new line j printA2 # loop done: li $v0, 4 # system call code for print_string la $a0, bye # load address of message into $a0 syscall # print the string li $v0, 10 # terminate program run and syscall # return control to system # END OF PROGRAM
修复后输出
1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 1 2 **** Thank you for running my program **** **************** Goodbye ***************** -- program is finished running --
内容的提问来源于stack exchange,提问作者TJream
相关产品推荐
相关产品推荐

