繁体   English   中英

汇编Mips程序主要调用

[英]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而不是复制代码。

我保留了您的prwordprbyte函数完整[不再使用]。 如果要使用它们,请考虑删除它们仍然具有的“ 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM