我正在尝试练习将 C 代码转换为 MIPS 汇编。我该如何将以下 collatz 函数转换为 MIPS?

问题描述 投票:0回答:1
uint32_t collatz(uint32_t n, int d) {
  /*   printf("%d\n", n);*/
  if (n != 1) {
    if (n % 2)
      return collatz(3 * n + 1, d + 1);
    else {
      return collatz(n / 2, d + 1);
    }
  }

  return d;
}

这是我试图在 MIPS Assembly 中重写的 C 函数。 我想在我的汇编版本中使用递归,并且我真的很难让该函数正常工作。

我有这个函数的汇编版本的驱动程序。

.data

arrow: .asciiz " -> "

.text

main:
    li      $sp,        0x7ffffffc      # initialize $sp

# PROLOGUE
    subu    $sp,        $sp,        8   # expand stack by 8 bytes
    sw      $ra,        8($sp)          # push $ra (ret addr, 4 bytes)
    sw      $fp,        4($sp)          # push $fp (4 bytes)
    addu    $fp,        $sp,        8   # set $fp to saved $ra

    subu    $sp,        $sp,        12  # save s0 and s1 on stack before using them
    sw      $s0,        12($sp)         # push $s0
    sw      $s1,        8($sp)          # push $s1
    sw      $s2,        4($sp)          # push $s2

    la      $s0,        xarr            # load address to s0

main_for:
    lw      $s1,        ($s0)           # use s1 for xarr[i] value
    li      $s2,        0               # use s2 for initial depth (steps)
    beqz    $s1,        main_end        # if xarr[i] == 0, stop.

# save args on stack rightmost one first
    subu    $sp,        $sp,        8   # save args on stack
    sw      $s2,        8($sp)          # save depth
    sw      $s1,        4($sp)          # save xarr[i]

    li      $v0,        1
    move    $a0,        $s1             # print_int(xarr[i])
    syscall 

    li      $v0,        4               # print " -> "
    la      $a0,        arrow
    syscall 

    jal     collatz                     # result = collatz(xarr[i])

    move    $a0,        $v0             # print_int(result)
    li      $v0,        1
    syscall 

    li      $a0,        10              # print_char('\n')
    li      $v0,        11
    syscall 

    addu    $s0,        $s0,        4   # make s0 point to the next element

    lw      $s2,        8($sp)          # save depth
    lw      $s1,        4($sp)          # save xarr[i]
    addu    $sp,        $sp,        8   # save args on stack
    j       main_for

main_end:
    lw      $s0,        12($sp)         # push $s0
    lw      $s1,        8($sp)          # push $s1
    lw      $s2,        4($sp)          # push $s2

# EPILOGUE
    move    $sp,        $fp             # restore $sp
    lw      $ra,        ($fp)           # restore saved $ra
    lw      $fp,        -4($sp)         # restore saved $fp
    jr      $ra                         # return to kernel

这是我的预期输出:


2 -> 1
4 -> 2
6 -> 8
8 -> 3
10 -> 6

这是我对该功能的最新实现:

# collatz function in MIPS Assembly
# Assumes n is in $a0 and d is in $a1
# Returns the result in $v0

    .text
    .globl collatz
collatz:
    addi    $sp, $sp, -12    # Allocate stack space for local variables and return address
    sw      $ra, 8($sp)      # Save return address
    sw      $a0, 4($sp)      # Save n
    sw      $a1, 0($sp)      # Save d

    # Check if n is 1 (base case)
    li      $t0, 1
    beq     $a0, $t0, base_case

    # Check if n is even or odd
    andi    $t1, $a0, 1      # t1 = n % 2
    beqz    $t1, even_case

    # Odd case: 3n + 1
    li      $t2, 3
    mul     $t2, $a0, $t2    # t2 = 3 * n
    addi    $t2, $t2, 1      # t2 = 3 * n + 1

    j       recursive_call

even_case:
    # Even case: n / 2
    srl     $t2, $a0, 1      # t2 = n / 2

recursive_call:
    # Prepare arguments for recursive call
    lw      $a0, 4($sp)      # Restore n
    lw      $a1, 0($sp)      # Restore d
    addi    $a1, $a1, 1      # Increment d

    move    $a0, $t2         # Update n
    jal     collatz          # Recursive call

    # Returning from recursive call
    j       end_function

base_case:
    # Base case: n is 1, return d
    lw      $v0, 0($sp)      # Load d into return value register $v0

end_function:
    lw      $ra, 8($sp)      # Restore return address
    addi    $sp, $sp, 12     # Deallocate stack space
    jr      $ra              # Return to caller

这是我得到的输出:

2 -> 2147476133
4 -> 2147476262
6 -> 2147476391
8 -> 2147476520
10 -> 2147476649

我从为该函数编写的先前版本中获得的其他输出包括一个像上面的大整数,除了所有输入的数字相同之外。我还得到了全 0 的输出。我还得到了算术溢出错误。

c assembly mips32
1个回答
0
投票

您没有正确地将参数从

main
传递到
collatz
$a0
中的值,第一个参数寄存器是对字符串“->”的引用,这不是你想要的。

© www.soinside.com 2019 - 2024. All rights reserved.