[英]Assembly Mips Program Main Calls
I am having trouble with my main program. 我的主程序遇到问题。 I need to allow bits to be passed into the function dumpb and dumbw and dumpreg (i think). 我需要允许将位传递到函数dumpb和dumbw和dumpreg(我认为)。 Currently I'm getting zeros as my output but I don't think that's what I'm supposed to be getting. 目前,我的输出为零,但我认为那不是我应该得到的。 Could someone help me please or at least point me in the right direction of where my mistakes are? 有人可以帮助我,或者至少将我的错误指向正确的方向吗?
.data
n_elem: .word 10
.text
.globl main
main:
jal dumpreg
jal prword
jal prchar
#insert element to dump
jal dumpb
#insert element to dump
jal dumpw
addi $v0, $0, 10 #exit program
syscall
dumpw:
addi $sp, $sp, -16 #allocates memory
sw $a0, 12($sp)
sw $v0, 8($sp)
sw $t0, 4($sp)
sw $t1, 0($sp)
lw $t0, 20($sp) # load n_elem
lw $t1, 16($sp) # load address
looptop:
beq $t0, $0, bailout
lw $a0, 0($t1) # a0 = address[i]
addi $v0, $0, 1
syscall
addi $t0, $t0, -1
addi $t1, $t1, 4
j looptop
bailout:
lw $t1, 0($sp)
lw $t0, 4($sp)
lw $v0, 8($sp)
lw $a0, 12($sp)
addi $sp, $sp, 16
jr $ra
dumpb:
addi $sp, $sp, -16
sw $a0, 12($sp)
sw $v0, 8($sp)
sw $t0, 4($sp)
sw $t1, 0($sp)
lw $t0, 20($sp) # load n_elem
lw $t1, 16($sp) # load address
looptopb:
beq $t0, $0, bailoutb
lb $a0, 0($t1) # a0 = address[i]
addi $v0, $0, 11
syscall
addi $t0, $t0, -1
addi $t1, $t1, 1
j looptopb
bailoutb:
lw $t1, 0($sp)
lw $t0, 4($sp)
lw $v0, 8($sp)
lw $a0, 12($sp)
addi $sp, $sp, 16
jr $ra
prspace:
addi $sp, $sp, -8
sw $a0, 0($sp)
sw $ra, 4($sp)
addi $a0, $0, ' '
addi $sp, $sp, -4 #push it
sw $a0, 0($sp)
jal prchar
addi $sp, $sp, 4
lw $a0, 0($sp)
lw $ra, 4($sp)
addi $sp, $sp, 8
jr $ra
prcomma:
addi $sp, $sp, -8
sw $a0, 0($sp)
sw $ra, 4($sp)
addi $a0, $0, ',' #
addi $sp, $sp, -4 #push it
sw $a0, 0($sp)
jal prchar
addi $sp, $sp, 4
lw $a0, 0($sp)
lw $ra, 4($sp)
addi $sp, $sp, 8
jr $ra
prnl:
addi $sp, $sp, -8
sw $a0, 0($sp)
sw $ra, 4($sp)
addi $a0, $0, 0x0A # 0xA new line char
addi $sp, $sp, -4 #push it
sw $a0, 0($sp)
jal prchar
addi $sp, $sp, 4
lw $a0, 0($sp)
lw $ra, 4($sp)
addi $sp, $sp, 8
jr $ra
prchar:
addi $sp, $sp, -8
sw $a0, 4($sp)
sw $v0, 0($sp)
lw $a0, 8($sp)
addi $v0, $0, 11
syscall
lw $v0, 0($sp)
lw $a0, 4($sp)
addi $sp, $sp, 8
jr $ra
prbyte:
addi $sp, $sp, -8
sw $a0, 4($sp)
sw $v0, 0($sp)
lw $a0, 8($sp)
addi $v0, $0, 1
syscall
lw $v0, 0($sp)
lw $a0, 4($sp)
addi $sp, $sp, 8
jr $ra
dumpreg:
addi $sp, $sp, -4
sw $ra, 0($sp)
jal prnl
addi $sp, $sp, -4
jal prspace
sw $a0, 0($sp)
jal prword
jal prspace
sw $a1, 0($sp)
jal prword
jal prspace
sw $t0, 0($sp)
jal prword
jal prspace
sw $t1, 0($sp)
jal prword
jal prspace
sw $t2, 0($sp)
jal prword
jal prspace
sw $t3, 0($sp)
jal prword
jal prspace
sw $t4, 0($sp)
jal prword
jal prspace
sw $s0, 0($sp)
jal prword
jal prspace
sw $s1, 0($sp)
jal prword
addi $sp, $sp, 4
jal prnl
lw $ra, 0($sp)
addi $sp, $sp, 4
jr $ra
prword:
addi $sp, $sp, -8
sw $a0, 4($sp)
sw $v0, 0($sp)
lw $a0, 8($sp)
addi $v0, $0, 1
syscall
lw $a0, 4($sp)
lw $v0, 0($sp)
addi $sp, $sp, 8
jr $ra
I was able to fix your program and get it working, but I had to do quite a bit of rework. 我能够修复您的程序并使它正常运行,但是我不得不做很多返工。
You were doing way too much push/pop on the stack. 您在堆栈上执行过多的推入/弹出操作。 Note that while the code was not technically wrong [for the most part], it was contrary to the mips ABI and the spirit of mips and, thus, was complicated. 请注意,尽管该代码在技术上没有错误(大部分情况下),但这与mips ABI和mips的精神背道而驰,因此很复杂。
You were pushing arguments onto the stack instead of passing them in registers. 您将参数推入堆栈,而不是将其传递到寄存器中。 This also added to the [needless] complexity. 这也增加了[不必要]的复杂性。 I changed all functions to pass arguments according to the ABI. 我更改了所有函数以根据ABI传递参数。
You were saving/restoring registers that are "callee owned", meaning that the callee need not preserve them and may change them at will: v*, a*, t* 您正在保存/恢复“被调用方所有”的寄存器,这意味着被调用方不需要保留它们,可以随意更改它们:v *,a *,t *
Saving v0 on the stack actually breaks the ABI as it's used for return values [and syscall numbers]. 将v0保存在堆栈上实际上会破坏ABI,因为它用于返回值[和系统调用号]。
Your program was incomplete (ie no array to dump) and, in main, you were calling functions without setting up the arguments for them. 您的程序不完整(即没有要转储的数组),并且主要是您在调用函数时未为其设置参数。
I simplified the really low level functions like prchar
. 我简化了像prchar
这样的底层函数。 Take special note that the single char output functions (eg prnl
) that called it, now use "tail call optimization", so they don't need a stack frame of their own. 需要特别注意的是,调用它的单个char输出函数(例如prnl
)现在使用“尾调用优化”,因此它们不需要自己的堆栈框架。
I changed dumpregs
to pre-store the regs and then call dumpw
instead of replicating the code. 我将dumpregs
更改为预先存储了regs,然后调用dumpw
而不是复制代码。
I left your prword
and prbyte
functions intact [they are no longer used]. 我保留了您的prword
和prbyte
函数完整[不再使用]。 If you want to use them, consider removing the "push arg on stack" interface they still have and convert to using $a0
instead. 如果要使用它们,请考虑删除它们仍然具有的“ push arg on stack”接口,并改为使用$a0
转换。
So, the code may look [quite] a bit alien to you [please pardon the gratuitous style cleanup]: 因此,代码对您可能看起来[有点]陌生[请原谅免费的样式清理]:
.data
n_elem: .word 10
array: .word 1,2,3,4,5,6,7,8,9,10
dumpw_msg: .asciiz "words:"
dumpb_msg: .asciiz "bytes:"
dumpreg_msg: .asciiz "regs:"
.text
.globl main
main:
jal prnl
jal dumpreg
# dump array as words
la $a0,dumpw_msg
li $v0,4
syscall
la $a0,array
lw $a1,n_elem
jal dumpw
# dump array as bytes
la $a0,dumpb_msg
li $v0,4
syscall
la $a0,array
lw $a1,n_elem
sll $a1,$a1,2 # get byte count
jal dumpb
addi $v0,$0,10 # exit program
syscall
# dumpw -- dump array as words
#
# arguments:
# a0 -- pointer to array
# a1 -- number of words in array
dumpw:
move $t1,$a0 # load address
move $t0,$a1 # load count
dumpw_loop:
ble $t0,$0,dumpw_done
# output a space
addi $v0,$0,11
addi $a0,$0,' '
syscall
lw $a0,0($t1) # a0 = address[i]
addi $v0,$0,1
syscall
addi $t0,$t0,-1
addi $t1,$t1,4
j dumpw_loop
dumpw_done:
# output a newline
addi $v0,$0,11
addi $a0,$0,0x0a
syscall
jr $ra
# dumpb -- dump array as bytes
#
# arguments:
# a0 -- pointer to array
# a1 -- number of bytes in array
dumpb:
move $t1,$a0 # load address
move $t0,$a1 # load count
dumpb_loop:
ble $t0,$0,dumpb_done
# output a space
addi $v0,$0,11
addi $a0,$0,' '
syscall
lb $a0,0($t1) # a0 = address[i]
addi $v0,$0,1
syscall
addi $t0,$t0,-1
addi $t1,$t1,1
j dumpb_loop
dumpb_done:
# output a newline
addi $v0,$0,11
addi $a0,$0,0x0a
syscall
jr $ra
# dumpreg -- dump registers
dumpreg:
addi $sp,$sp,-36
sw $ra,0($sp)
# pre-store the registers we wish to dump
sw $a0,4($sp)
sw $a1,8($sp)
sw $t0,12($sp)
sw $t1,16($sp)
sw $t2,20($sp)
sw $t3,24($sp)
sw $s0,28($sp)
sw $s1,32($sp)
# output the identifying message
la $a0,dumpreg_msg
li $v0,4
syscall
# now, because of the pre-store, we can reuse the array dumper
addiu $a0,$sp,4 # point to the dumped registers array
addi $a1,$0,8 # get number of words to dump
jal dumpw
# restore the dumped register values
lw $a0,4($sp)
lw $a1,8($sp)
lw $t0,12($sp)
lw $t1,16($sp)
lw $t2,20($sp)
lw $t3,24($sp)
lw $s0,28($sp)
lw $s1,32($sp)
lw $ra,0($sp)
addi $sp,$sp,36
jr $ra
# prword -- dump a word as integer (currently unused)
prword:
addi $sp,$sp,-8
sw $a0,4($sp)
sw $v0,0($sp)
lw $a0,8($sp)
addi $v0,$0,1
syscall
lw $a0,4($sp)
lw $v0,0($sp)
addi $sp,$sp,8
jr $ra
# prbyte -- print a byte (currently unused)
prbyte:
addi $sp,$sp,-8
sw $a0,4($sp)
sw $v0,0($sp)
lw $a0,8($sp)
addi $v0,$0,1
syscall
lw $v0,0($sp)
lw $a0,4($sp)
addi $sp,$sp,8
jr $ra
# prspace -- print a space
prspace:
addi $a0,$0,' '
j prchar
# prcomma -- print a comma
prcomma:
addi $a0,$0,','
j prchar
# prnl -- print a newline
prnl:
addi $a0,$0,0x0A
j prchar
# prchar -- print an ascii char
prchar:
addi $v0,$0,11
syscall
jr $ra
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.