【发布时间】: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 以使其成为我想要的。谢谢,