2016-06-07 1 views
0

메인 프로그램에 문제가 있습니다. 나는 비트가 함수 dumpb와 dumbw와 dumpreg (나는 생각한다)에 전달되도록 허용 할 필요가있다. 현재 출력으로 제로를 얻고 있지만 그것이 내가 얻고있는 것으로 생각하지 않습니다. 누군가 나를 제발 도와 주거나 적어도 내 실수가있는 곳에서 올바른 방향으로 나를 가리킬 수 있습니까?Assembly Mips Program 메인 콜

.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 
+0

아무도이 문제를 해결할 수 있습니다. 당신은 그것이 작동하지 않는다고 확신하지 못합니다. –

답변

1

프로그램을 수정하여 작동 시키지만 재 작업을 많이해야했습니다.

스택에 너무 많은 푸시/팝을하고있었습니다. 코드가 기술적으로 잘못되어있는 것은 아니지만 mips의 ABI와 mips의 정신에 위배되어 복잡했습니다.

인수를 레지스터로 전달하는 대신 스택으로 푸시했습니다. 이것은 또한 [불필요한] 복잡성에 추가되었습니다. 나는 ABI에 따라 논쟁을 통과시키기 위해 모든 기능을 바꿨다.

당신은 수신자가이를 보존 할 필요가 마음대로 변경할 수 있음을 의미한다 "호출자가 소유"하는/복원 레지스터, 저장했다

: 브이 * A *, t의 *를 스택에 V0 저장

실제로 ABI는 반환 값 [및 syscall 번호]에 사용되는대로 분리됩니다.

프로그램이 완료되지 않았으므로 (즉, 덤프 할 배열이 없음) 주 (main)에서는 인수를 설정하지 않고 함수를 호출했습니다.

prchar과 같은 저수준 함수를 단순화했습니다. 특별히 호출 한 단일 문자 출력 함수 (예 : prnl)는 "꼬리 호출 최적화"를 사용하므로 자체 스택 프레임이 필요하지 않습니다.

dumpregs을 변경하여 reg를 미리 저장 한 다음 코드를 복제하는 대신 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