簡體   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