简体   繁体   English

汇编Mips程序主要调用

[英]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]. 我保留了您的prwordprbyte函数完整[不再使用]。 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.

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