如何在MIPS汇编中向函数传递数组

3

这个任务要求编写一个 MIPS 函数,该函数接受一个数组作为参数,将数组中所有元素相加并返回结果。主要问题是我对汇编语言不熟悉,并不确定如何在汇编语言中传递数组。目前我所拥有的代码如下:

# Title: homework2.asm
# Author: Jacob Suarez
# Date: 9/28/14
# Purpose: Create a function that can find the sum of the elements in an array, and run two arrays through it

# Text Segment
.text          
.globl  __start 
__start: 

    li  $t0, 0         # $t0 <- sum
    li  $a0, 0         # $a0 <- array index

# Set arr1 as the argument for the sumArr function
    la  $t4, arr1
    sw  $t4, arrx

# Set upper bound of array index
    li  $t9, 4         

# Call function to calculate the sum of arr1
    jal sumArr

    sw  $v0, sum1
    la  $a0, sum1

# Print sum1 from $a0
    li      $v0, 1         
    syscall 
    la      $a0, end1
    li      $v0, 4 
    syscall 

# Reset function arguments to 0
    li  $t0, 0         # $t0 <- sum
    li  $a0, 0         # $a0 <- array index

# Set arr2 as the argument for the sumArr function
    la  $t4, arr2
    sw  $t4, arrx

# Set upper bound of array index
    li  $t9, 5         

# Call function to calculate the sum of arr2
    jal sumArr

    sw  $v0, sum2
    la  $a0, sum2

# Print sum2 from $a0
    li      $v0, 1         
    syscall 
    la      $a0, end2
    li      $v0, 4 
    syscall 

# End program
    li  $v0, 10
    syscall

sumArr:
    lw  $t2, arrx($a0)  # $t2 <- value in the array
    add $t0, $t0, $t2   # sum += A[i]
    addi    $a0, $a0, 4 # i++ in bytes
    blt $a0, $t9, sumArr

# Move contents of $t0 to $a0
    move    $t0, $a0

# Return
    jr  $ra

# Data Segment
    .data 
    arrx:   .space  100
    arr1:   .word   8,12,20,40
    arr2:   .word   15,25,35,55,-129
    sum1:   .word   0
    sum2:   .word   0
    end1:   .asciiz " is the sum of arr1.\n"
    end2:   .asciiz " is the sum of arr2.\n"
# end of file  homework2.asm 

现在,这一切都运行得很好,但问题是结果似乎只是从未初始化的内存空间中提取出来的,所以我只得到像4268501128这样显然错误的数字,因此我认为我的问题是如何将数组传递给函数,具体来说是代码的这一部分:
# Set arr1 as the argument for the sumArr function
    la  $t4, arr1
    sw  $t4, arrx

任何建议吗?还是我的问题完全不同?
编辑:我认为我的问题实际上可能是数组没有正确初始化,或者我从中获取数据的方式,但我无法确定是否真的是这种情况,因为在我初始化它们的方式上似乎没有任何问题。

将数组传递给子例程,有两种选择:将数组的完整副本推入堆栈(按值传递,通常不是正确的答案),或将数组的基地址推送到堆栈上,然后相对于该地址进行寻址(按引用传递)。别忘了子例程还需要知道数组的维数,这样它才能执行适当的相对寻址计算;这可以是硬编码或附加参数。如果您看到了错误的数据,则地址可能是错误的……或者您真的没有初始化数组。 - keshlam
好的,我试图将arr1和arr2的地址传递给arrx,但我想我一定是走错了路。看来在等待更多答案的同时,我会继续尝试。 - Onamar
我认为你不能使用sw $t4,arrx,我相信你需要使用la $??,arrx sw $t4,($??),因为MIPS不能直接从/向内存中加载/存储。 - puppydrum64
1个回答

0

所以你已经把这个部分搞对了:

# Set arr1 as the argument for the sumArr function
la  $t4, arr1

但不幸的是,这部分是错误的:

sw  $t4, arrx

MIPS 被称为 RISC(精简指令集计算机),这意味着它的指令比像英特尔 x86 这样的计算机少。MIPS 无法直接将寄存器存储到常量地址,例如此处所示。为了将 $t4 存储在地址 arrx,您需要执行类似于以下操作。(请注意,对于此示例,我选择了 $t3,只是因为它尚未被使用。)

la $t4,arr1    ;load the address of arr1 into $t4
la $t3,arrx    ;load the address of arrx into $t3
sw $t4,0($t3)  ;store the address of arr1 at the first 4 bytes of arrx

在这些指令的序列之后,如果你能够以某种方式实时查看代码运行时的源代码中的 .data 部分,那么我们的数据段将会如下所示:
.data 
    arrx:   .word arr1
            .space  96
    arr1:   .word   8,12,20,40
    arr2:   .word   15,25,35,55,-129
    sum1:   .word   0
    sum2:   .word   0
    end1:   .asciiz " is the sum of arr1.\n"
    end2:   .asciiz " is the sum of arr2.\n"

一些MIPS汇编器,包括MARS/SPIM,将lwsw $reg, symbol汇编为lui/sw,使用$at作为地址的高半部分。也就是说,它们像la一样支持它作为伪指令。如果您要重用地址,则使用单独的la+swlw需要总共三条指令,因此只有在您要重用地址时才更好。 (或者如果您想让学生确保他们了解机器实际上可以做什么。) - Peter Cordes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接