[英]Assembly Mips Program Main Calls
我的主程序遇到问题。 我需要允许将位传递到函数dumpb和dumbw和dumpreg(我认为)。 目前,我的输出为零,但我认为那不是我应该得到的。 有人可以帮助我,或者至少将我的错误指向正确的方向吗?
.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
我能够修复您的程序并使它正常运行,但是我不得不做很多返工。
您在堆栈上执行过多的推入/弹出操作。 请注意,尽管该代码在技术上没有错误(大部分情况下),但这与mips ABI和mips的精神背道而驰,因此很复杂。
您将参数推入堆栈,而不是将其传递到寄存器中。 这也增加了[不必要]的复杂性。 我更改了所有函数以根据ABI传递参数。
您正在保存/恢复“被调用方所有”的寄存器,这意味着被调用方不需要保留它们,可以随意更改它们:v *,a *,t *
将v0保存在堆栈上实际上会破坏ABI,因为它用于返回值[和系统调用号]。
您的程序不完整(即没有要转储的数组),并且主要是您在调用函数时未为其设置参数。
我简化了像prchar
这样的底层函数。 需要特别注意的是,调用它的单个char输出函数(例如prnl
)现在使用“尾调用优化”,因此它们不需要自己的堆栈框架。
我将dumpregs
更改为预先存储了regs,然后调用dumpw
而不是复制代码。
我保留了您的prword
和prbyte
函数完整[不再使用]。 如果要使用它们,请考虑删除它们仍然具有的“ push arg on stack”接口,并改为使用$a0
转换。
因此,代码对您可能看起来[有点]陌生[请原谅免费的样式清理]:
.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.