簡體   English   中英

為什么我的 MIPS 基本轉換器在當前值之后打印出前一個循環中的值?

[英]Why is my MIPS base converter printing out the values from a previous loop after the current values?

我對 MIPS 很陌生,這讓我完全困惑。 我制作了一個轉換基數的程序,它第一次運行良好,但是當它循環時,它會顯示來自循環先前迭代的其他寄存器的值。 輸出如下。 我已經嘗試了我能想到的一切,但我沒有想法......

Enter a decimal number: 10
The number in base 2 is 00000000000000000000000000001010
The number in base 4 is 0000000000000022
The number in base 16 is 0000000A
The number in base 8 is 0000000012

您想輸入另一個號碼嗎? 1

Enter a decimal number: 11
The number in base 2 is 0000000000000000000000000000101100000000000000220000000A0000000012

The number in base 4 is 00000000000000230000000A0000000012

The number in base 16 is 0000000B0000000012

The number in base 8 is 0000000013

您想輸入另一個號碼嗎?

    .text
    .globl __start

__start:
    la $a0, prompt              # Prompt for a base10 integer
    li $v0, 4
    syscall

    li $v0, 5                   
    syscall

    move $a0, $v0               

    jal bin                     
    jal base4
    jal hex
    jal base8

    la $a0, endl                
    li $v0, 4
    syscall     

    la $a0, repeat              
    li $v0, 4
    syscall

    li $v0, 5                
    syscall

    beqz $v0, eop               

    la $a0, endl                
    li $v0, 4
    syscall

    j __start                

eop:    
    li $v0,10                       # End Of Program
        syscall     



##########################################################
#
#   BASE 16
#
##########################################################  

hex:    
    sub $sp, $sp, 24            # Push register onto stack
    sw $a0, 0($sp)
    sw $s0, 4($sp)
    sw $s1, 8($sp)
    sw $s2, 12($sp)
    sw $s3, 16($sp)
    sw $s4, 20($sp)

    move $s2, $a0               # Move a0 to s2

    la $a0, ans3                # Display string before hex answer
    li $v0, 4
    syscall

    li $s0, 8                   # 8 digits for hex word
    la $s3, hexresult           # Hex string set up here

hexloop:
    rol $s2, $s2, 4             # Start with leftmost digit
    and $s1, $s2, 0xf           # Mask 15 digits in s2 and place results in s1
    ble $s1, 9, hexprint        # If s1 <= 9, go to print
    add $s1, $s1, 7             # Else s1 = s1 + 7 (to get A-F)

hexprint:
    add $s1, $s1, 48            # Add 48 (30 hex) to get ascii code
    sb $s1,($s3)                # Store byte in result. s3 -> result
    add $s3, $s3, 1             # s3 = s3 + 1
    add $s0, $s0, -1            # s0 = s0 - 1
    bnez $s0, hexloop           # If s0 != 0, go to hexloop
    la $a0, hexresult           # display result

    li $v0, 4
    syscall

    jr $ra                      # Return
##########################################################
#
#   BASE 2
#
#########################################################

bin:    
    sub $sp, $sp, 24            # Push register onto stack
    sw $a0, 0($sp)
    sw $s0, 4($sp)
    sw $s1, 8($sp)
    sw $s2, 12($sp)
    sw $s3, 16($sp)
    sw $s4, 20($sp)

    move $s2, $a0               # Move a0 to s2

    la $a0, ans1                # Display string before bin answer
    li $v0, 4
    syscall

    li $s0, 32                  # 32 digits for base4 word
    la $s3, binresult           # Bin string set up here

binloop:
    rol $s2, $s2, 1             # Start with leftmost digit
    and $s1, $s2, 1             # Mask one digit in s2 and place results in s1


binprint:
    add $s1, $s1, 48            # Add 48 (30 hex) to get ascii code
    sb $s1,($s3)                # Store byte in result. s3 -> result
    add $s3, $s3, 1             # s3 = s3 + 1
    add $s0, $s0, -1            # s0 = s0 - 1
    bnez $s0, binloop           # If s0 != 0, go to binloop
    la $a0, binresult           # display result

    li $v0, 4
    syscall

    la $a0, endl
    li $v0, 4
    syscall

    jr $ra                      # Return

##########################################################
#
#   BASE 4
#
#########################################################       

base4:  
    sub $sp, $sp, 24            # Push register onto stack
    sw $a0, 0($sp)
    sw $s0, 4($sp)
    sw $s1, 8($sp)
    sw $s2, 12($sp)
    sw $s3, 16($sp)
    sw $ra, 20($sp)

    move $s2, $a0               # Move a0 to s2

    la $a0, ans2                # Display string before BASE 4 answer
    li $v0, 4
    syscall

    li $s0, 16                  # 16 digits for base4 word
    la $s3, base4result         # Bin string set up here

base4loop:
    rol $s2, $s2, 2             # Start with leftmost digit
    and $s1, $s2, 3             # Mask one digit in s2 and place results in s1

fourprint:
    add $s1, $s1, 48            # Add 48 (30 hex) to get ascii code
    sb $s1,($s3)                # Store byte in result. s3 -> result
    add $s3, $s3, 1             # s3 = s3 + 1
    add $s0, $s0, -1            # s0 = s0 - 1
    bnez $s0, base4loop         # If s0 != 0, go to binloop

    la $a0, base4result         # display result
    li $v0, 4
    syscall

    la $a0, endl
    li $v0, 4
    syscall

    jr $ra                      # Return

##########################################################
#
#   BASE 8
#
#########################################################           

base8:  
    sub $sp, $sp, 24            # Push register onto stack
    sw $a0, 0($sp)
    sw $s0, 4($sp)
    sw $s1, 8($sp)
    sw $s2, 12($sp)
    sw $s3, 16($sp)
    sw $ra, 20($sp)

    move $s2, $a0               # Move a3 to s2

    la $a0, endl
    li $v0, 4
    syscall     

    la $a0, ans4                # Display string before bin answer
    li $v0, 4
    syscall

    li $s0, 10              #  digits for octal word
    la $s3, octresult           # Bin string set up here

    rol $s2, $s2, 2             # Start with leftmost digit
    and $s1, $s2, 0x7           # Mask 7 digits in s2 and place results in s1

base8loop:
    rol $s2, $s2, 3             # Start with leftmost digit
    and $s1, $s2, 0x7           # Mask 7 digits in s2 and place results in s1


base8print:
    add $s1, $s1, 48            # Add 48 (30 hex) to get ascii code
    sb $s1,($s3)                # Store byte in result. s3 -> result
    add $s3, $s3, 1             # s3 = s3 + 1
    add $s0, $s0, -1            # s0 = s0 - 1
    bnez $s0, base8loop         # If s0 != 0, go to binloop
    la $a0, octresult           # display result

    li $v0, 4
    syscall     


    jr $ra                      # Return


.data

binresult:  .space 32
base4result:.space 16
hexresult:  .space  8
octresult:  .space 10
endl:       .asciiz "\n"
prompt:     .asciiz "Enter a decimal number: "
ans1:       .asciiz "The number in base 2 is "
ans2:       .asciiz "The number in base 4 is "
ans3:       .asciiz "The number in base 16 is "
ans4:       .asciiz "The number in base 8 is "
repeat:     .asciiz "Would you like to input another number? "

您使用 syscall 4 打印的字符串必須是 ASCIIZ,即帶有零終止符的 ASCII。 因此,您需要在每個字符串的最后一個字符后存儲一個值為 0 的字節。 為了能夠存儲額外的字節,您需要為每個字符串保留一個額外的字節(即binResult等的.space 33 )。

其實,只是增加了與保留的字節數.space應該是不夠的,因為.space應該零初始化的內存。 但是為每個字符串添加一個額外的sb只是為了確保不會受到太大傷害。

我在理解所有帶有一些沖突注釋和寄存器用法的代碼時遇到了一些困難(例如,輸入 27 並且十六進制返回 0)。 當我運行它,通過它加強,我我看到了rol垃圾的東西。 不知道,因為我只運行了一次或兩次。

所以,我使用不同的方法重新編碼。 所有四個鹼基的代碼現在是通用的。 我做了十六進制和八進制。 我把基地 4 和基地 2 留給你去做。

無論如何,這是代碼[請原諒無償的風格清理]:

    .text
    .globl  main

main:
    la      $a0,prompt              # Prompt for a base10 integer
    li      $v0,4
    syscall

    # get the value
    li      $v0,5
    syscall
    move    $s7,$v0

    ###jal      bin
    ###jal      base4
    jal     hex
    jal     oct

    la      $a0,endl
    li      $v0,4
    syscall

    la      $a0,repeat
    li      $v0,4
    syscall

    li      $v0,5
    syscall

    beqz    $v0,eop

    la      $a0,endl
    li      $v0,4
    syscall

    j       main

eop:
    li      $v0,10                  # End Of Program
    syscall

#   BASE 16
hex:
    la      $a0,hexmsg              # Display string before hex answer
    li      $a1,0x0F                # mask for hex digit
    li      $a2,28                  # initial right shift amount
    li      $a3,4                   # right shift decrement
    j       numdump

#   BASE 8
oct:
    la      $a0,octmsg              # Display string before hex answer
    li      $a1,0x07                # mask for octal digit
    li      $a2,30                  # right shift amount
    li      $a3,3                   # right shift decrement
    j       numdump

# numdump -- dump out a number in an alternate base
#
# arguments:
#   a0 -- pointer to string for prefix
#   a1 -- mask for digit
#   a2 -- initial right shift amount
#   a3 -- amount to decrement shift by
#   s7 -- number value
numdump:
    li      $v0,4
    syscall

    la      $t3,result              # output string set up here

numloop:
    srlv    $t0,$s7,$a2             # slide the digit right
    and     $t0,$t0,$a1             # mask the digit
    lb      $t0,digits($t0)         # get the ascii value

    sb      $t0,0($t3)              # store into result buffer
    addi    $t3,$t3,1               # advance result pointer

    sub     $a2,$a2,$a3             # reduce shift amount -- more to do?
    bgez    $a2,numloop             # yes, loop

    sb      $zero,0($t3)            # store end of string

    la      $a0,result              # display result
    li      $v0,4
    syscall

    la      $a0,endl
    syscall

    jr      $ra                     # Return

    .data

result:     .space      40
digits:     .asciiz     "0123456789ABCDEF"

endl:       .asciiz     "\n"
prompt:     .asciiz     "Enter a decimal number: "
b2msg:      .asciiz     "The number in base 2 is "
b4msg:      .asciiz     "The number in base 4 is "
hexmsg:     .asciiz     "The number in base 16 is "
octmsg:     .asciiz     "The number in base 8 is "
repeat:     .asciiz     "Would you like to input another number? "

這是一個稍微更緊湊的版本,它需要對 common 函數少一個參數:

    .text
    .globl  main

main:
    la      $a0,prompt              # Prompt for a base10 integer
    li      $v0,4
    syscall

    # get the value
    li      $v0,5
    syscall
    move    $s7,$v0

    ###jal      bin
    ###jal      base4
    jal     hex
    jal     oct

    la      $a0,endl
    li      $v0,4
    syscall

    la      $a0,repeat
    li      $v0,4
    syscall

    li      $v0,5
    syscall

    beqz    $v0,eop

    la      $a0,endl
    li      $v0,4
    syscall

    j       main

eop:
    li      $v0,10                  # End Of Program
    syscall

#   BASE 16
hex:
    la      $a0,hexmsg              # Display string before hex answer
    li      $a1,4                   # number of bits in a digit
    li      $a2,28                  # initial right shift amount
    j       numdump

#   BASE 8
oct:
    la      $a0,octmsg              # Display string before hex answer
    li      $a1,3                   # number of bits in a digit
    li      $a2,30                  # right shift amount
    j       numdump

# numdump -- dump out a number in an alternate base
#
# arguments:
#   a0 -- pointer to string for prefix
#   a1 -- number of bits in a digit
#   a2 -- initial right shift amount
#   s7 -- number value
#
# registers:
#   a3 -- digit mask
numdump:
    li      $v0,4
    syscall

    la      $t3,result              # output string set up here

    # create digit mask from number of bits in a digit
    li      $a3,1                   # mask = 1
    sllv    $a3,$a3,$a1             # mask <<= digit width (for hex, 0x10)
    subiu   $a3,$a3,1               # bump down for mask (for hex, 0x0F)

numloop:
    srlv    $t0,$s7,$a2             # slide the digit right
    and     $t0,$t0,$a3             # mask the digit
    lb      $t0,digits($t0)         # get the ascii value

    sb      $t0,0($t3)              # store into result buffer
    addi    $t3,$t3,1               # advance result pointer

    sub     $a2,$a2,$a1             # reduce shift amount -- more to do?
    bgez    $a2,numloop             # yes, loop

    sb      $zero,0($t3)            # store end of string

    la      $a0,result              # display result
    li      $v0,4
    syscall

    la      $a0,endl
    syscall

    jr      $ra                     # Return

    .data

result:     .space      40
digits:     .asciiz     "0123456789ABCDEF"

endl:       .asciiz     "\n"
prompt:     .asciiz     "Enter a decimal number: "
b2msg:      .asciiz     "The number in base 2 is "
b4msg:      .asciiz     "The number in base 4 is "
hexmsg:     .asciiz     "The number in base 16 is "
octmsg:     .asciiz     "The number in base 8 is "
repeat:     .asciiz     "Would you like to input another number? "

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM