Assembly 如何使用汇编语言(MIPS)中的堆栈修改注册表?

Assembly 如何使用汇编语言(MIPS)中的堆栈修改注册表?,assembly,mips,qtspim,Assembly,Mips,Qtspim,我对汇编语言中的寄存器有问题。我似乎不明白如何用我原来程序中的堆栈修改注册表。我正在使用MIPS 我要做的基本上是: 修改以使其使用堆栈传入和传出参数。同样,$a和$v寄存器不应用于传递参数。只能使用堆栈。请不要修改代码的逻辑,只更改使用堆栈所需的内容 # Register Usage # $t0 # $t1 # $t2 # $t3 # $t4 # $t5 # $t6 # $t7 # $t8 # $t9 temporarily ####

我对汇编语言中的寄存器有问题。我似乎不明白如何用我原来程序中的堆栈修改注册表。我正在使用MIPS

我要做的基本上是:

修改以使其使用堆栈传入和传出参数。同样,$a和$v寄存器不应用于传递参数。只能使用堆栈。请不要修改代码的逻辑,只更改使用堆栈所需的内容

#       Register Usage
#   $t0
#   $t1
#   $t2
#   $t3
#   $t4
#   $t5
#   $t6
#   $t7
#   $t8
#   $t9     temporarily
###########################################################
        .data
array_pointer_p:        .word 0     # holds address of dynamic array (address)
array_size_p:           .word 0     # hold size of dynamic array (value)        
array_sum_p:            .word 0     # sum variable initialized to 0
###########################################################
        .text
main:
# calling subprogram read_values
    jal make_array                      # call read_values subprogram
                                        # arguments IN: NONE
                                        # arguments OUT: array base address and size

# store returned values (array base address & size) into static variables
    la $t9, array_pointer_p             # load the address of variable array_pointer_p into register $t9
    sw $v0, 0($t9)                      # store the true address of dynamic array into static variable
                                        # memory[0 + array_pointer_p] <-- $v0

    la $t9, array_size_p                # load the address of variable array_size_p into register $t9
    sw $v1, 0($t9)                      # store value of array into static variable
                                        # memory[0 + array_size_p] <-- $v1


# load array base address & size from static variables
    la $t9, array_pointer_p             # load the address of variable array_pointer_p into register $t9
    lw $a0, 0($t9)                      # load the true address of dynamic array into static variable
                                        # $a0 <-- memory[0 + array_pointer_p]

    la $t9, array_size_p                # load the address of variable array_size_p into register $t9
    lw $a1, 0($t9)                      # store value of array into static variable
                                        # $a1 <-- memory[0 + array_size_p]

# calling subprogram read_values
    jal read_values                     # call read_values subprogram
                                        # arguments IN: array base address and size
                                        # arguments OUT: array sum

# store returned values (array sum) into static variables
    la $t9, array_sum_p                 # load the address of variable array_sum_p into register $t9
    sw $v0, 0($t9)                      # store value of array sum into static variable
                                        # memory[0 + array_sum_p] <-- $v0


# load array base address & size from static variables
    la $t9, array_pointer_p             # load the address of variable array_pointer_p into register $t9
    lw $a0, 0($t9)                      # load the true address of dynamic array into static variable
                                        # $a0 <-- memory[0 + array_pointer_p]

    la $t9, array_size_p                # load the address of variable array_size_p into register $t9
    lw $a1, 0($t9)                      # store value of array into static variable
                                        # $a1 <-- memory[0 + array_size_p]

# calling subprogram read_values
    jal print_backwards                 # call read_values subprogram
                                        # arguments IN: array base address and size
                                        # arguments OUT: NONE


# load array sum & size from static variables
    la $t9, array_sum_p                 # load the address of variable array_sum_p into register $t9
    lw $a0, 0($t9)                      # load value of array sum into static variable
                                        # $a0 <-- memory[0 + array_sum_p]

    la $t9, array_size_p                # load the address of variable array_size_p into register $t9
    lw $a1, 0($t9)                      # store value of array size into static variable
                                        # $a1 <-- memory[0 + array_size_p]

# calling subprogram read_values
    jal print_average                   # call read_values subprogram
                                        # arguments IN: array sum and size
                                        # arguments OUT: NONE

mainEnd:    
    li $v0, 10                          # halt
    syscall
###########################################################
#       make_array subprogram
#
#   Subprogram description:
#       The first subprogram 'make_array' will ask the user for the number of integers to be
#       read and dynamically declares an array to hold them. It receives no arguments IN and
#       has two arguments OUT, the base address of the dynamically declared array and it size.
#       Do not forget to validate array size (array size should be greater than zero).
#
###########################################################
#       Arguments IN and OUT of subprogram
#   $a0
#   $a1
#   $a2
#   $a3
#   $v0     Holds array pointer (address)
#   $v1     Holds array size (value)
#   $sp
#   $sp+4
#   $sp+8
#   $sp+12
###########################################################
#       Register Usage
#   $t0  Holds array pointer (address)
#   $t1  Holds array size pointer (address)
#   $t2  Holds array size, temporarily  
###########################################################
        .data
make_array_prompt_p:    .asciiz "Enter size of the array to allocate (greater than 0): "
make_array_invalid_p:   .asciiz "Array size you entered is incorrect (array size should be greater than zero)\n"
###########################################################
        .text
make_array:

make_array_loop:
    li $v0, 4                           # prompt for array size
    la $a0, make_array_prompt_p
    syscall

    li $v0, 5                           # reads integer for array size
    syscall

    blez $v0, make_array_invalid_size   # branch to error section as array size is less than or equal to zero

    move $t2, $v0                       # store valid array size in register $t2

    li $v0, 9                           # dynamically allocate an array (using system call 9)
    move $a0, $t2                       # puts array size in register $a0
    sll $a0, $a0, 2                     # multiply array size by 4, as word in MIPS is 4 bytes
    syscall

    b make_array_end                    # branch unconditionally to the end of subprogram

make_array_invalid_size:
    li $v0, 4                           # prints an error saying that array size is less than or equal to zero
    la $a0, make_array_invalid_p
    syscall

    b make_array_loop                   # branch unconditionally back to beginning of the loop

make_array_end:
    move $v0, $v0                       # return address of dynamic array in register $v0 (array_pointer)
    move $v1, $t2                       # store size of dynamic array in register $v1 (array_size)

    jr $ra                              # jump back to the main
###########################################################
#       read_values subprogram
#
#   Subprogram description:
#       The second subprogram 'read_values' which receives two arguments IN, the array base address
#       and its size. Also, it makes sure entered numbers are between 0 and +250 exclusive. It returns
#       (OUT) the sum of valid numbers read in the appropriate registers.
#
###########################################################
#       Arguments IN and OUT of subprogram
#   $a0
#   $a1
#   $a2
#   $a3
#   $v0     Holds sum
#   $v1
#   $sp
#   $sp+4
#   $sp+8
#   $sp+12
###########################################################
#       Register Usage
#   $t0     Holds array base address / array pointer
#   $t1     Holds array size / loop count down
#   $t2     Holds sum
#   $t3     Holds value -120
#   $t4     Holds value 150
###########################################################
        .data
read_values_prompt_p:   .asciiz "Enter a value between (-120 to +150) exclusive: "
read_values_invalid_p:  .asciiz "Invalid entry\n"
###########################################################
        .text
read_values:
# store arguments IN into temporarily registers so we don't lose them
    move $t0, $a0                       # array base address        
    move $t1, $a1                       # array size

# initialization
    li $t2, 0                           # initialize sum to 0
    li $t3, -120                        # holds value -120
    li $t4, 150                         # holds value 150

read_values_loop:
    blez $t1, read_values_exit_loop     # branch to the read_values_exit_loop if loop counter is 
                                        # less than or equal to zero

    li $v0, 4                           # prompts to enter a value
    la $a0, read_values_prompt_p
    syscall

    li $v0, 5                           # reads an integer value
    syscall

    bge $v0, $t4, read_values_error     # branch to the error if value if greater
                                        # than or equal to 150

    ble $v0, $t3, read_values_error     # branch to the error if value if less
                                        # than or equal to -120

    add $t2, $t2, $v0                   # adds the number to the sum

    sw $v0, 0($t0)                      # store the number in the array

    addi $t0, $t0, 4                    # increment array pointer (address) to next word (each word is 4 bytes)
    addi $t1, $t1, -1                   # decrement array count down (index)  by 1

    b read_values_no_error              # branch unconditionally to no_error label to
                                        # skip printing error massage for valid entries

read_values_error:
    li $v0, 4                           # prints an error message
    la $a0, read_values_invalid_p
    syscall

read_values_no_error:
    b read_values_loop                  # branch unconditionally to the beginning of the loop

read_values_exit_loop:
    move $v0, $t2                       # return sum in register $v0

read_values_end:
    jr $ra                              # jump back to the main
###########################################################
#      print_backwards subprogram
#
#   Subprogram description:
#       The third subprogram 'print_backwards' receives as arguments IN the base address of the
#       array and its size. It has no arguments OUT. It outputs the array in reverse order one number
#       per line at a time.
#
###########################################################
#       Arguments IN and OUT of subprogram
#   $a0     Holds array pointer (address)
#   $a1     Holds array size (value)
#   $a2
#   $a3
#   $v0
#   $v1
#   $sp
#   $sp+4
#   $sp+8
#   $sp+12
###########################################################
#       Register Usage
#   $t0     Holds array base address / array pointer
#   $t1     Holds array size / loop count down
#   $t2     temporarily
###########################################################
        .data
print_backwards_array_p:    .asciiz     "Array (in backwards): "
print_backwards_nextline_p: .asciiz     "\n" 
###########################################################
        .text
print_backwards:
# store arguments IN into temporarily registers so we don't lose them
    move $t0, $a0                       # move array pointer (address) to $t0
    move $t1, $a1                       # move array size (value) to $t1

# adjust array base address: new base address = old base address + 4 * (count - 1)
    add $t2, $t1, -1                    # adjust count (n) to last element index (n-1)
    sll $t2, $t2, 2                     # multiply element index number by element size (4 bytes)
    add $t0, $t0, $t2                   # address of last element

    li $v0, 4                           # prints array is:
    la $a0, print_backwards_array_p
    syscall

    li $v0, 4                           # prints nextline ("\n")
    la $a0, print_backwards_nextline_p
    syscall

print_backwards_loop:
    blez $t1, print_backwards_exit_loop # branch to print_backwards_exit_loop if counter is less than or equal to zero

# print value from array
    li $v0, 1
    lw $a0, 0($t0)                      # $a0 <-- memory[$t0 + 0] // load a value from memory to register $a0
    syscall

    li $v0, 4                           # prints nextline ("\n")
    la $a0, print_backwards_nextline_p
    syscall

    addi $t0, $t0, -4                   # decrement array pointer (address) to next word (each word is 4 bytes)
    addi $t1, $t1, -1                   # decrement array counter (index)

    b print_backwards_loop              # branch unconditionally back to beginning of the loop

print_backwards_exit_loop:
    li $v0, 4                           # prints nextline ("\n")
    la $a0, print_backwards_nextline_p
    syscall

print_backwards_end:    
    jr $ra                              # jump back to the main
###########################################################
#      print_average subprogram
#
#   Subprogram description:
#       The fourth subprogram 'print_average' which receives as arguments IN the 'total' and 'count'
#       and has no arguments OUT. It outputs the average of the numbers read to 5 decimal places using
#       only integer commands. You will declare and use static variables to hold the base address of the
#       array, count of element, and the sum of values of the elements.
#
###########################################################
#       Arguments IN and OUT of subprogram
#   $a0     Holds array sum (value)
#   $a1     Holds array size (value)
#   $a2
#   $a3
#   $v0
#   $v1
#   $sp
#   $sp+4
#   $sp+8
#   $sp+12
###########################################################
#       Register Usage
#   $t0     holds sum/remainder
#   $t1     holds count
#   $t2     holds default number of decimal points (constant value 7)
#   $t3     holds constant value 10
###########################################################
        .data
print_average_sum_p:        .asciiz     "Given sum: "
print_average_count_p:      .asciiz     "Given count: "
print_average_average_p:    .asciiz     "Array average (up-to 7 decimal points using integer instructions): "
print_average_nextline_p:   .asciiz     "\n" 
###########################################################
        .text
print_average:
# store arguments IN into temporarily registers so we don't lose them
    move $t0, $a0                       # move array sum to $t0
    move $t1, $a1                       # move array size (value) to $t1

# initialization
    li $t2, 5                           # calculate average up-to 7 digit accuracy
    li $t3, 10                          # initialize $t2 to constant value 10

# print sum
    li $v0, 4                           # print sum is:
    la $a0, print_average_sum_p
    syscall

    li $v0, 1                           # print sum value
    move $a0, $t0
    syscall

# print nextline
    li $v0, 4                           # prints nextline ("\n")
    la $a0, print_average_nextline_p
    syscall

# print count
    li $v0, 4                           # print count is:
    la $a0, print_average_count_p
    syscall

    li $v0, 1                           # print count value
    move $a0, $t1
    syscall

# print nextline
    li $v0, 4                           # prints nextline ("\n")
    la $a0, print_average_nextline_p
    syscall

# print average 
    li $v0, 4                           # print average is:
    la $a0, print_average_average_p
    syscall

    div $t0, $t1                        # divide sum by count
    mflo $a0                            # put quotient in register $a0
    mfhi $t0                            # put remainder in register $t0

    li $v0, 1                           # print quotient
    syscall

    li $v0, 11                          # print period character (ASCII character 46)
    li $a0, 46
    syscall


print_average_calculation_loop:
    blez $t2, print_average_exit_loop   # branch to exit if we have printed up-to specified decimal points

    mul $t0, $t0, $t3                   # multiply remainder by 10
    div $t0, $t1                        # divide (remainder * 10) by count
    mflo $a0                            # put quotient in register $a0
    mfhi $t0                            # put remainder in register $t0

    li $v0, 1                           # print quotient
    syscall

    addi $t2, $t2, -1                   # decrement decimal point counter

    b print_average_calculation_loop    # branch unconditionally to the print_average_calculation_loop

print_average_exit_loop:

print_average_end:
    jr $ra                              # jump back to the main
########################################################### 
#注册用法
#$t0
#1美元
#2美元
#t3美元
#t4美元
#t5美元
#$t6
#$t7
#$t8
#暂付t9元
###########################################################
.数据
数组指针:字0保存动态数组的地址(地址)
数组_size_p:.字0#保留动态数组的大小(值)
数组_sum_p:.字0#sum变量初始化为0
###########################################################
.文本
主要内容:
#调用子程序read_值
jal生成数组调用读取值子程序
#中的参数:无
#参数输出:数组基址和大小
#将返回值(数组基址和大小)存储到静态变量中
la$t9,数组指针p#将变量数组指针p的地址加载到寄存器$t9中
sw$v0,0($t9)#将动态数组的真实地址存储到静态变量中

#内存[0+数组\u指针\u p]哪个部分导致您出现问题?你知道如何读写堆栈吗?只需将参数放在调用方的堆栈上,然后将它们加载回被调用方。不要忘记通过移动堆栈指针来分配和取消分配空间。您可能希望编辑您的问题以引用“寄存器”而不是“注册表”。是哪部分导致了您的问题?你知道如何读写堆栈吗?只需将参数放在调用方的堆栈上,然后将它们加载回被调用方。不要忘记通过移动堆栈指针来分配和取消分配空间。您可能希望编辑您的问题以引用“寄存器”而不是“注册表”