【问题标题】:How to put jr $ra to directly correct place?如何将 jr $ra 直接放到正确的位置?
【发布时间】:2019-12-16 06:55:16
【问题描述】:

我想跳转到print_comp,但现在我写了这段代码,它显示了

尝试在 0x00400324 处执行非指令

在 QTspim 中。我希望我能学会如何放置它。

另外,我不会跳print10,但可以jump print8 因为在str2int 中使用了jr $ra。请告诉我为什么,我很感激。 这是我的代码:

# ----------------------------------
# Data Segment
.data
msg:    .ascii  "Info: the inputted 32-bit unsigned number can be binary with prefix \"b\",\n"
        .ascii  "\t\t\t     or octal with prefix \"0\",\n"
        .ascii  "\t\t\t     or decimal without prefix,\n"
        .asciiz "\t\t\t     or hexadecimal with prefix\"0x\".\n"

prompt: .asciiz "\nEnter a number: "
ansBin: .asciiz "Convert it to Binary: b"
ansDec: .asciiz "Convert it to Decimal: "
ansOct: .asciiz "Convert it to Octal: 0"
ansHex: .asciiz "Convert it to Hexadecimal: 0x"
comp:   .asciiz "\nDo you wanna continue(y/n)? \n"
newLine:    .asciiz "\n"
end:    .asciiz "\nEnd\n"
buffer: .space  33

# ----------------------------------
# Text/Code Segment

.text
.globl main
main:
    la  $a0, msg    # print msg
    li  $v0, 4
    syscall

print_promt:
    la  $a0, prompt # print prompt
    li  $v0, 4
    syscall

    la  $a0, buffer # this is the input $a0 is the whole thing eg.b10100
    li  $a1, 33     # the length of a1 is 33
    li  $v0, 8      # read String
    syscall

    lb      $s0, 0($a0) # $s0 is the first char
                        # Each character is a byte long
                        # now $s0 = 1st char

    bne     $s0, 98, notBin # 98 is 'b' in ASCII code

    addi    $a0, $a0, 1 # check 2nd char ( no b,0,0x )
                        # now $s0 = 2nd char
    lb      $s0,0($a0)
    move    $s1, $s0
    li      $t5, 2      # binary ($a2 = 2)

endofnotBin:
    # ----- Binary to Decimal ----- 
    jal     str2int         # go str2int, Binary to Decimal
    add     $t6, $v1, $zero # keep fot print10  
    move    $a2, $v1        # $v1 is the ans of Decimal
                            # Octal starts with $a2
    jal print10
    # ----- End -----       

#--------------------------------------------------------
    # ----- Decimal to Octal -----  
    jal print8
    move    $a2, $v1
    # ----- End -----   

    # ----- Just print Decimal -----
    jal print10
    move    $a2, $v1
    # ----- End -----   

    # ----- Decimal to Hexadecimal -----
    jal print16

#--------------------------------------------------------

    # ------------- ENDING -------------    
print_comp:
    la  $a0, comp       # print comp
    li  $v0, 4          # print String
    syscall

    la  $a0, buffer
    li  $a1, 33         # length of a1 is 33
    li  $v0, 8          # read integer, a place to write Y/N
    syscall

    lb  $s0, 0($a0)
    beq $s0, 89, print_promt        # if input "Y" (89 is Y in ASCII) go print_promt
    beq $s0, 121, print_promt       # if input "y" (121 is y in ASCII) go print_promt

    beq $s0, 78, theend     # if input "N" (78 is N in ASCII) go theend
    beq $s0, 110, theend    # if input "n" (110 is n in ASCII) go theend

theend:
    la  $a0, end        # print end
    li  $v0, 4
    syscall

    # -----
    # Done, exit program.
    li      $v0, 10         # call code for exit
    syscall                 # system call

#--------------------------------------------------------------------
notBin: # TODO
    beq $s0, 48, isOct  # 48 is '0' in ASCII code
    beq $s0, 49, isDex  # 49 is '1' in ASCII code
    beq $s0, 50, isDex  # 50 is '2' in ASCII code
    beq $s0, 51, isDex  # 51 is '3' in ASCII code
    beq $s0, 52, isDex  # 52 is '4' in ASCII code
    beq $s0, 53, isDex  # 53 is '5' in ASCII code
    beq $s0, 54, isDex  # 54 is '6' in ASCII code
    beq $s0, 55, isDex  # 55 is '7' in ASCII code
    beq $s0, 56, isDex  # 56 is '8' in ASCII code
    beq $s0, 57, isDex  # 57 is '9' in ASCII code

isOct:
    addi    $a1,$a0,1
    lb      $s0,0 ($a1)
    bne     $s0, 120, isHex     # 120 is 'x' in ASCII code
    lb      $s0,0 ($a0)
    jal     print2
    j       endofnotBin

isHex:
    addi    $a0,$a0,1           # start to read 3rd code permently
    lb      $s0,0 ($a0)         # load new $s0
    jal     print2

    j       endofnotBin

#--------Whem the prefix is Decimal ---------   
isDex:
    # ----- Decimal to Binary -----
    jal print2
    add     $t5, $zero, $a0     # copy one for Octal and Hexadecimal
    add     $t0, $zero, $a0     # $t0 = $a0
    add     $t1, $zero, $zero   # $t1 = 0
    addi    $t3, $zero, 1       # $t3 = 1
    sll     $t3, $t3, 31        # move the mask
    addi    $t4, $zero, 32      # count the loop

loop12:
    and     $t1, $t0, $t3       # and the input with the mask
    beq     $t1, $zero, print12     # Branch to print if its 0

    add     $t1, $zero, $zero   # Zero out $t1
    addi    $t1, $zero, 1       # Put a 1 in $t1
    j print12


print12: 
    li   $v0, 1
    move $a0, $t1
    syscall

    srl  $t3, $t3, 1
    addi $t4, $t4, -1
    bne  $t4, $zero, loop12

    # ----- Decimal to Octal -----
    move $a2,$t5

    jal print8
    move    $a2, $v1
    # ----- Decimal to Hexadecimal -----
    jal print16

    j   print_comp
    j   endofnotBin
#--------Whem the prefix is Decimal ---------   


.end main

# ----------
# procedure: str2int
# $a0 = starting address of input string excluding prefix
# $a2 = base
# return value = $v1
# -------------------------------------------------------------------------
.globl str2int
str2int:
    lb      $s0, 0($a0) # beacuse $a0 + 1 in Line 44 
                        # $s0 now read the 2nd char (num)
                        # and count the length from 2nd - end
    move    $a1, $a0    # $a1 ← $a0 = ($a0 + 1)

#----↓↓↓------------------------------------------------------------------
length: 
    lb      $s0, 0($a1)     # $s0 = 0 + $a1
                            # $s0 = 0 + ($a1 + 1) in second time
    beq     $s0, 10, endString #if $s0 = 10 (new line in ASCII) , go endString
    addi    $a1, $a1, 1     # $a1 = $a1 + 1
    j       length          # looping $a1 + 1 to chack every character
#----↓↓↓------------------------------------------------------------------
endString:
    sub     $t3, $a1, $a0   # new $t3 =  $a1(length of String except char) - $a0( first char / 1 )
    # $a1 is the length of input digits
    # ("length to endString" is a way to find the length)
    add     $t4, $zero, $t3
    li      $t1,1   # $t1 = 1
    li      $v0,1   # $v0 = 1
    li      $v1,0   # $v1 = 0
    li      $s2,0   # $s2 = 0
    li      $t0,0   # $t0 = 0   
#----↓↓↓------------------------------------------------------------------
movego:
    # $t3 = $A1 IS THE LENGTH
    # precess of binary to decimal
    beq     $t0, $t3, strloop   # if $t0 = $t3(length of str) , go strloop
    mul     $v0, $v0, 2         # $v0 = 1 x 2 x 2 x 2....x 2
    addi    $t0, $t0, 1         # $t0 = $t0 + 1
    j       movego              # loop again

strloop:
    div     $v0,$v0,2           # $v0 = $v0 / 2
    bgt     $t1,$t4,printSum    # if $t1 > $t4 , go printsum
    lb      $s1, 0 ($a0)        # load new $a0 to $s0 
    sub     $s1,$s1,48          # $s1 = $s1 - 48 ( the ascii of "0" ) = to check is 1 or 0
    addi    $a0,$a0,1           # $a0 + 1 check the next char
    addi    $t1,$t1,1           # $t1 + 1 let > $t4
    mul     $v1,$v0,$s1         # $v1 = $s2 x $v1
    add     $s2,$s2,$v1         # $s2 = $s2 + $v1
    j       movego

printSum:
    move    $v1, $s2            # result put in $v1
    jr      $ra
.end str2int
#--------------------------------------------------------------------

# ----------
# procedure: print2
# $a2 = the integer to print
# return value: $v1 = $a2
# -----------
.globl print2
print2:
    la  $a0, ansBin     # print ansBin
    li  $v0, 4          # print String
    syscall

    la  $a0, newLine    # print newLine
    li  $v0, 4
    syscall

.end print2
# ----------
# procedure: print10
# $a2 = the integer to print
# return value: $v1 = $a2
# -----------
.globl print10
print10:
    la  $a0, ansDec             # print ansDec
    li  $v0, 4
    syscall

    addi    $a0,$t6,0           # print the answer of decimal number
    li  $v0, 1
    syscall

    la  $a0, newLine            # print newLine
    li  $v0, 4
    syscall
.end print10

# -----------
# procedure: print8
# $a2 = the integer to print
# return value: $v1 = $a2
# -----------
.globl print8

print8:
    # decimal --> octal
        li $s5, 10
        li $s3, 2
        div $t2,$a2,$s5
        mul $t2,$t2,$s3
        add $v1,$a2,$t2

exit_print8:
    la  $a0, ansOct             # print ansOct
    li  $v0, 4
    syscall

    addi    $a0,$v1,0           # print the answer of decimal number
    li  $v0, 1
    syscall

    la  $a0, newLine            # print newLine
    li  $v0, 4
    syscall

.end print8


# ----------
# procedure: print16
# $a2 = the integer to print
# return value: $v1 = $a2
# -----------
.globl print16
print16:
            la      $a0, ansHex             # print ansHex
            li      $v0, 4
            syscall

            add         $s0, $a2, $zero
            move        $a0, $s0        

            bne     $s0, $zero, non_zero

            addi    $a0, $s0, 48 # $a0 = 0, so print character ’0’

            li      $v0, 11      # call code to print character

            syscall

            j   exit_l

non_zero:   lui $t0,0xf000  # $t0 = 0xf0000000

            li  $t2,0       # $t2 = 0, think of the usage of $t2 below

            li  $t3,1       # $t3 = 1

            li  $t4,0       # $t4 = 0

loop:       beq $t4, 8, exit_l  # if $t4 > 8 go exit_l

            and $t1, $s0, $t0

            srl $t1, $t1, 28

            movn    $t2,$t3,$t1 # if($t1!=0) $t2=$t3 else do nothing

            beq $t2,$zero,shift

            bge $t1,10,letter   # 0<= $t1 < 10

            addi    $a0,$t1,48  # $a0 is equal to ‘0’~’9’

            j   print_char

letter:     addi    $a0,$t1,55  # 10 <= $t1 <=15, $a0 is equal to ’A’~’F’

print_char: li  $v0,11

            syscall

shift:      sll $s0,$s0,4

            addi    $t4,$t4,1

            j   loop    

exit_l:
            la  $a0, newLine            # print newLine
            li  $v0, 4
            syscall
.end print16

【问题讨论】:

  • “我想跳到 print_comp” 为什么?这是跳转后的下一行,所以你可以删除跳转指令。
  • 嗨迈克尔,我已经尝试过了,但仍然出现错误,“尝试执行非指令”使我无法继续打印出 print_comp,我在 str2int 中使用了 jr $ra 但是当我使用 jr $ra 打印 16 时,它会打印一些无用的内容,但程序可以继续运行 print_comp 直到程序结束。所以我想知道需要以哪种方式添加其他 jr $ra 以使其成为我想要的。谢谢,

标签: mips qtspim


【解决方案1】:

解决它!

jr $ra 表示跳转到“main方法”并继续。

.globl main: 

j one #when one is finished & receive the $ra ,continue the following execution
j two #same
j three #same

.end main

one:
   (codes)
   jr $ra 
#tell main that "one" is finished, go back to the main and continue to start "two"

two:
   (codes)
   jr $ra
#same

three:
   (codes)
   jr $ra
#same

希望对他人有所帮助!

【讨论】:

  • 其实jr是跳转返回,$ra保存的是之前用jal跳转链接设置的返回地址。我建议阅读有关 MIPS 中函数调用的更多信息。
猜你喜欢
  • 1970-01-01
  • 2014-09-26
  • 2019-07-13
  • 2017-07-29
  • 1970-01-01
  • 1970-01-01
  • 2021-12-20
  • 1970-01-01
  • 2011-05-21
相关资源
最近更新 更多