求助:MIPS汇编打印100字符数组为每行10个,首行正常后续出错
嘿,我来帮你搞定这个MIPS汇编的打印问题!看起来你的print函数只处理了第一行的10个字符,没有循环遍历整个数组,也没正确处理换行和指针移动,所以后面的内容打印出错了。
先把你给出的截断代码整理成代码块方便查看:
#v20180326# # Prints string to stdout with length $a1 # $a0 -> string # $a1 -> length print: # save s-Regs addi $sp, $sp, -8 sw $s0, 0($sp) sw $s1, 4($sp) # save params move $s0, $a0 # (后续代码截断,推测仅处理了单次10字符打印)
核心问题分析
- 没有外层循环来处理10行的打印逻辑,只执行了一次单行打印
- 打印完第一行后,没有把字符串指针移动到下一行的起始位置
- 缺少每行结束后的换行操作,无法形成正方形布局
- 没有递减剩余需要打印的字符数,无法判断什么时候停止
修正后的完整代码
我给你写了一个专门的print_square函数,完美实现每行10个、共10行的正方形打印:
#v20180326# # Prints string to stdout in 10x10 square (10 chars per line) # $a0 -> string (100 characters total) # $a1 -> length (should be 100 for this use case) print_square: # Save s-registers and return address to stack (符合MIPS调用规范) addi $sp, $sp, -12 sw $s0, 0($sp) # 保存字符串基地址 sw $s1, 4($sp) # 保存剩余待打印字符数 sw $ra, 8($sp) # 保存返回地址(因为要调用系统调用) # 初始化寄存器 move $s0, $a0 move $s1, $a1 # 外层循环:处理每一行的打印 print_loop: bgtz $s1, print_line # 还有字符没打印?那就打印一行 j print_exit # 所有字符打印完,退出函数 # 打印单行的10个字符 print_line: li $t0, 10 # 每行字符计数器(最多10个) move $t1, $s0 # 当前行的起始指针 # 内层循环:打印当前行的每个字符 line_loop: beqz $t0, print_newline # 已经打印10个字符?跳去打换行 beqz $s1, print_newline # 没有剩余字符了?直接打换行收尾 # 打印单个字符(系统调用11:打印ASCII字符) lb $a0, 0($t1) li $v0, 11 syscall addi $t1, $t1, 1 # 指针移动到下一个字符 addi $t0, $t0, -1 # 单行计数器减1 addi $s1, $s1, -1 # 剩余字符数减1 j line_loop # 打印换行符(ASCII码10) print_newline: li $a0, 10 li $v0, 11 syscall move $s0, $t1 # 更新字符串基地址为下一行的起始位置 j print_loop # 函数退出:恢复寄存器并返回 print_exit: lw $s0, 0($sp) lw $s1, 4($sp) lw $ra, 8($sp) addi $sp, $sp, 12 jr $ra # 返回调用者
关键修正点说明
- 新增了外层循环
print_loop,负责遍历所有行,直到100个字符全部打印 - **内层
line_loop**处理每行的10个字符打印,同时兼容剩余字符不足10的情况(虽然你是刚好100个,但这样函数更健壮) - 每次打印完一行后,更新字符串指针到下一行的起始位置,确保下一行从正确的地方开始
- 加入了换行逻辑,每行结束后打印换行符,完美形成正方形布局
- 严格遵循MIPS调用规范,正确保存和恢复所有用到的寄存器,避免破坏调用者的上下文
使用示例
调用这个函数的时候,只要把你的100字符数组地址放到$a0,长度100放到$a1就行:
.data my_square_array: .byte 'a','b','c','d','e','f','g','h','i','j', 'k','l','m','n','o','p','q','r','s','t', # ... 这里继续补全到100个字符 ... .text main: la $a0, my_square_array li $a1, 100 jal print_square # 退出程序 li $v0, 10 syscall
内容的提问来源于stack exchange,提问作者LazerDance
相关产品推荐
相关产品推荐

