装配Mips程序主要调用

时间:2016-06-07 18:19:43

标签: assembly mips

我的主程序遇到问题。我需要允许位传递到函数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

1 个答案:

答案 0 :(得分:1)

我能够修复你的程序并使其正常工作,但我不得不做一些返工。

你在堆栈上做了太多的推/弹。请注意,虽然代码在技术上并不是[大多数],但它与mips ABI和mips的精神相反,因此很复杂。

您正在将参数推送到堆栈而不是将它们传递到寄存器中。这也增加了[不必要的]复杂性。我根据ABI改变了所有函数来传递参数。

您正在保存/恢复被叫"被叫方拥有的注册表#34;这意味着被叫方无需保留它们并可随意更改它们:v *,a *,t *

在堆栈上保存v0实际上会破坏ABI,因为它用于返回值[和系统调用号码]。

您的程序不完整(即没有要转储的数组),并且在main中,您在调用函数时没有为它们设置参数。

我简化了prchar等真正的低级功能。请特别注意,调用它的单个字符输出函数(例如prnl)现在使用"尾调用优化",因此它们不需要自己的堆栈帧。 / p>

我更改dumpregs预先存储了regs,然后调用dumpw而不是复制代码。

我完全保留了prwordprbyte个功能[不再使用它们]。如果你想使用它们,可以考虑删除堆栈上的" push arg"他们仍然拥有的界面,转而使用$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