[英]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.