You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MARS MIPS汉诺塔实现中输出步骤编号缺失问题求助

MIPS汉诺塔实现:修复步骤编号缺失问题

需求与问题

用MARS MIPS实现汉诺塔,要求输出写入TOWER_OF_HANOI.txt,格式要求:

Step 1: A=>B
Step 2: A=>C
Step 3: B=>C
...

当前输出缺失步骤编号,显示为:

Step : A=>B
Step : A=>C
...

现有代码

# Towers of Hanoi
# MIPS assembly implementation (tested with MARS)

.data
prompt: .asciiz "Enter a number: "
part1: .asciiz "\nStage "
part2: .asciiz ": "
part3: .asciiz "==>"
fout:   .asciiz "TOWER_OF_HANOI.txt"      # filename for output
temp: .byte               # store the character A, B, C in the file

.text
globl main
#########################################################################
# Open (for writing) a file that does not exist
    li   $v0, 13       # system call for open file
    la   $a0, fout     # output file name
    li   $a1, 1        # Open for writing (flags are 0: read, 1: write)
    li   $a2, 0        # mode is ignored
    syscall            # open a file (file descriptor returned in $v0)
    move $s6, $v0      # save the file descriptor 
  
#########################################################################
main:
    li $v0,  4          # print string
        la $a0,  prompt
        syscall
        li $v0,  5          # read integer
        syscall

    # parameters for the routine
        add $a0, $v0, $zero # move to $a0
        li $a1, 'A'
        li $a2, 'B'
        li $a3, 'C'

        jal hanoi           # call hanoi routine
###########################################################
# Đóng file
    li   $v0, 16       # system call for close file
    move $a0, $s6      # file descriptor to close
    syscall            # close file
    
        li $v0, 10          # exit
        syscall
###########################################################
hanoi:

    #save in stack
    addi $sp, $sp, -20 
    sw   $ra, 0($sp)
    sw   $s0, 4($sp)
    sw   $s1, 8($sp)
    sw   $s2, 12($sp)
    sw   $s3, 16($sp)

    add $s0, $a0, $zero
    add $s1, $a1, $zero
    add $s2, $a2, $zero
    add $s3, $a3, $zero

    addi $t1, $zero, 1
    beq $s0, $t1, output

    recur1:

        addi $a0, $s0, -1
        add $a1, $s1, $zero
        add $a2, $s3, $zero
        add $a3, $s2, $zero
        jal hanoi

        j output

    recur2:

        addi $a0, $s0, -1
        add $a1, $s3, $zero
        add $a2, $s2, $zero
        add $a3, $s1, $zero
        jal hanoi

    exithanoi:

        lw   $ra, 0($sp)        # restore registers from stack
        lw   $s0, 4($sp)
        lw   $s1, 8($sp)
        lw   $s2, 12($sp)
        lw   $s3, 16($sp)

        addi $sp, $sp, 20       # restore stack pointer

        jr $ra
##################################################################################3
    output:

        li $v0,  4              # print string
        la $a0,  part1
        syscall
        
          # Write to file just opened
    li   $v0, 15       # system call for write to file
    move $a0, $s6      # file descriptor 
    la   $a1, part1   # address of buffer from which to write
    li   $a2, 5       # hardcoded buffer length
    syscall            # write to file

        
        li $v0,  4              # print string
        la $a0,  part2
        syscall
        
          # Write to file just opened
    li   $v0, 15       # system call for write to file
    move $a0, $s6      # file descriptor 
    la   $a1, part2   # address of buffer from which to write
    li   $a2, 2       # hardcoded buffer length
    syscall            # write to file
        
        li $v0,  11             # print character
        add $a0, $s1, $zero
        sb $a0, temp
        syscall
        
          # Write to file just opened
    li   $v0, 15       # system call for write to file
    move $a0, $s6      # file descriptor 
    la   $a1, temp     # address of buffer from which to write
    li   $a2, 1        # hardcoded buffer length
    syscall            # write to file
       
        li $v0,  4              # print string
        la $a0,  part3
        syscall
        
          # Write to file just opened
    li   $v0, 15       # system call for write to file
    move $a0, $s6      # file descriptor 
    la   $a1, part3   # address of buffer from which to write
    li   $a2, 3       # hardcoded buffer length
    syscall            # write to file
        
        li $v0,  11             # print character
        add $a0, $s2, $zero
        sb $a0, temp
        syscall
        
          # Write to file just opened
    li   $v0, 15       # system call for write to file
    move $a0, $s6      # file descriptor 
    la   $a1, temp     # address of buffer from which to write
    li   $a2, 1       # hardcoded buffer length
    syscall            # write to file

    
    
        beq $s0, $t1, exithanoi
        j recur2

尝试过的无效方案

  • 模拟C/C++引用传参实现,未生效;
  • 使用全局变量/$gp寄存器存储计数器,但未处理整数转ASCII的关键步骤,调试无果。

修复方案

核心问题是缺少全局步骤计数器和整数转ASCII写入文件的逻辑,修复后的完整代码如下:

# Towers of Hanoi
# MIPS assembly implementation (tested with MARS)

.data
prompt: .asciiz "Enter a number: "
part1: .asciiz "\nStep "  # 修正为需求的Step字符串
part2: .asciiz ": "
part3: .asciiz "=>"       # 修正为需求的=>格式
fout:   .asciiz "TOWER_OF_HANOI.txt"      # filename for output
temp: .byte               # store the character A, B, C in the file
step_counter: .word 0     # 全局步骤计数器
temp_str: .space 2        # 临时存储步骤编号的ASCII字符串

.text
globl main
#########################################################################
# Open (for writing) a file that does not exist
    li   $v0, 13       # system call for open file
    la   $a0, fout     # output file name
    li   $a1, 1        # Open for writing (flags are 0: read, 1: write)
    li   $a2, 0        # mode is ignored
    syscall            # open a file (file descriptor returned in $v0)
    move $s6, $v0      # save the file descriptor 
  
#########################################################################
main:
    li $v0,  4          # print string
    la $a0,  prompt
    syscall
    li $v0,  5          # read integer
    syscall

    # 初始化步骤计数器为0
    la $t0, step_counter
    sw $zero, 0($t0)

    # parameters for the routine
    add $a0, $v0, $zero # move to $a0
    li $a1, 'A'
    li $a2, 'B'
    li $a3, 'C'

    jal hanoi           # call hanoi routine
###########################################################
# Close file
    li   $v0, 16       # system call for close file
    move $a0, $s6      # file descriptor to close
    syscall            # close file
    
    li $v0, 10          # exit
    syscall
###########################################################
hanoi:

    #save in stack
    addi $sp, $sp, -20 
    sw   $ra, 0($sp)
    sw   $s0, 4($sp)
    sw   $s1, 8($sp)
    sw   $s2, 12($sp)
    sw   $s3, 16($sp)

    add $s0, $a0, $zero
    add $s1, $a1, $zero
    add $s2, $a2, $zero
    add $s3, $a3, $zero

    addi $t1, $zero, 1
    beq $s0, $t1, output

recur1:
    addi $a0, $s0, -1
    add $a1, $s1, $zero
    add $a2, $s3, $zero
    add $a3, $s2, $zero
    jal hanoi

    j output

recur2:
    addi $a0, $s0, -1
    add $a1, $s3, $zero
    add $a2, $s2, $zero
    add $a3, $s1, $zero
    jal hanoi

exithanoi:
    lw   $ra, 0($sp)        # restore registers from stack
    lw   $s0, 4($sp)
    lw   $s1, 8($sp)
    lw   $s2, 12($sp)
    lw   $s3, 16($sp)

    addi $sp, $sp, 20       # restore stack pointer
    jr $ra
##################################################################################
output:
    # 递增步骤计数器
    la $t0, step_counter
    lw $t2, 0($t0)
    addi $t2, $t2, 1
    sw $t2, 0($t0)

    # 打印Step到控制台
    li $v0,  4
    la $a0,  part1
    syscall
    
    # 写入Step到文件
    li   $v0, 15
    move $a0, $s6
    la   $a1, part1
    li   $a2, 6       # "\nStep "的字节长度
    syscall

    # 打印步骤编号到控制台
    li $v0, 1
    move $a0, $t2
    syscall

    # 将步骤编号转为ASCII并写入文件
    la $t3, temp_str
    li $t4, 10
    div $t2, $t4
    mfhi $t5       # 个位
    mflo $t6       # 十位
    beq $t6, $zero, single_digit
    # 两位数处理
    addi $t6, $t6, 48
    sb $t6, 0($t3)
    addi $t5, $t5, 48
    sb $t5, 1($t3)
    li $a2, 2
    j write_num
single_digit:
    # 一位数处理
    addi $t5, $t5, 48
    sb $t5, 0($t3)
    li $a2, 1
write_num:
    li   $v0, 15
    move $a0, $s6
    move $a1, $t3
    syscall

    # 打印: 到控制台
    li $v0,  4
    la $a0,  part2
    syscall
    
    # 写入: 到文件
    li   $v0, 15
    move $a0, $s6
    la   $a1, part2
    li   $a2, 2
    syscall

    # 打印起始塔到控制台
    li $v0,  11
    add $a0, $s1, $zero
    sb $a0, temp
    syscall
    
    # 写入起始塔到文件
    li   $v0, 15
    move $a0, $s6
    la   $a1, temp
    li   $a2, 1
    syscall

    # 打印=>到控制台
    li $v0,  4
    la $a0,  part3
    syscall
    
    # 写入=>到文件
    li   $v0, 15
    move $a0, $s6
    la   $a1, part3
    li   $a2, 2
    syscall

    # 打印目标塔到控制台
    li $v0,  11
    add $a0, $s2, $zero
    sb $a0, temp
    syscall
    
    # 写入目标塔到文件
    li   $v0, 15
    move $a0, $s6
    la   $a1, temp
    li   $a2, 1
    syscall

    beq $s0, $t1, exithanoi
    j recur2

修复要点

  1. 新增全局计数器:在.data段添加step_counter,main中初始化为0,每次进入output时递增;
  2. 整数转ASCII:MARS的文件写入只能处理字节/字符串,因此需要将整数编号转为对应的ASCII字符(数字+48得到ASCII值),支持一位和两位数;
  3. 修正字符串常量:把part1改为"\nStep ",part3改为"=>",匹配需求格式;
  4. 调整写入长度:根据实际字符串长度修改syscall 15的$a2参数,避免写入多余或缺失字节。

内容的提问来源于stack exchange,提问作者Lucifer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 08:10:55