string 在 MIPS/Assembler 中将 ASCII 数字字符串转换为 int

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15940331/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 01:52:49  来源:igfitidea点击:

Convert String of ASCII digits to int in MIPS/Assembler

arraysstringintmipsatoi

提问by user1730099

Im writing some MIPS code to take a string of ASCII digits and convert the string into an integer. The string is entered by the user and can be at most 10 digits in length. My code works fine and uses the obvious method of performing looped addition after multiplying the Least Significant number in the string by a power of ten determined by the index of the array, starting from the last digit entered (10^0) to the first digit entered (10^n, n=number of digits in the array).

我正在编写一些 MIPS 代码来获取一串 ASCII 数字并将该字符串转换为整数。该字符串由用户输入,长度最多为 10 位。我的代码工作正常,并在将字符串中的最低有效数乘以由数组索引确定的 10 的幂后使用执行循环加法的明显方法,从输入的最后一位数字 (10^0) 开始到第一位数字输入(10^n,n=数组中的位数)。

I was wondering if there was an alternate method that would be quicker or shorter to write. In particular, I wanted to know if using a logical bit shift might make this process shorter. Any ideas for optimizing or improving this code would be greatly appreciated!

我想知道是否有一种替代方法可以更快或更短地编写。特别是,我想知道使用逻辑位移是否会使这个过程更短。任何优化或改进此代码的想法将不胜感激!

Also, as a side note, I would like to call the gets and readInt subroutines using jal, but because gets and readInt both call subroutines, using jal in the main method to call gets or readInt causes problems. Any ideas how to get around this? Thanks again Cheers

另外,作为旁注,我想使用 jal 调用 gets 和 readInt 子例程,但是因为 gets 和 readInt 都调用子例程,所以在 main 方法中使用 jal 来调用 gets 或 readInt 会导致问题。任何想法如何解决这个问题?再次感谢干杯

PS: sorry for the formatting of the comments in this code, copy and pasting from MARS simulator into the stack overflow text box caused the alignment to be off :/

PS:抱歉这段代码中注释的格式,从MARS模拟器复制粘贴到堆栈溢出文本框导致对齐关闭:/

#IO
#Prompts user to input 10 ascii digits into an array
#Converts the string of digits into a single int
#Also handles any number of digits between 1 and 10 
#Returns 0 if non-digit chars are entered into the string

.data           #declaration of vars follows
array: .space 11    #reserves space for a 10 elem array
char: .space 2
prompt: .asciiz "Please enter 10 numbers, then press ENTER:  \n"
null: .asciiz ""
space: .ascii " "
newline: .asciiz "\n"
.text           #instructions follow

main:
la $a0, prompt      #load prompt message into $a0 for syscall
li $v0, 4               #load syscall to print string
syscall         #print prompt message
j readInt               #call readInt function to get user input string         

gets:           #read multiple chars from keyboard buffer until ENTER key,
                            #add NULL char and store into buffer pointed to by *array
                            #passed to the subroutine
la $s1, array       #set base address of array to s1
loop:           #start of read loop
jal getc        #jump to getc subroutine
lb $t0, char        #load the char from char buffer into t0, stripping null
sb $t0, 0($s1)      #store the char into the nth elem of array
lb $t1, newline     #load newline char into t1
beq $t0, $t1, done  #end of string?  jump to done
addi $s1, $s1, 1    #increments base address of array
j loop          #jump to start of read loop

getc:           #read char from keyboard buffer and return ascii value
li $v0, 8       #call code for read string
la $a0, char        #load address of char for read
li $a1, 2       #length of string is 1byte char and 1byte for null
syscall         #store the char byte from input buffer into char
jr $ra          #jump-register to calling function

readInt:        #read string of ascii digits, store into a local variable and  
                    #convert into integer, return that int unless string contains 
                    #non-integers 
j gets          #let s1 be top address of array, let s0 be the digitcounter
done:           #let s2 be the sum total
addi $s1, $s1, -1   #reposition array pointer to last char before newline char
la $s0, array       #set base address of array to s0 for use as counter
addi $s0, $s0, -1   #reposition base array to read leftmost char in string
add $s2, $zero, $zero   #initialize sum to 0
li $t0, 10      #set t0 to be 10, used for decimal conversion
li $t3, 1
lb $t1, 0($s1)      #load char from array into t1
blt $t1, 48, error  #check if char is not a digit (ascii<'0')
bgt $t1, 57, error  #check if char is not a digit (ascii>'9')
addi $t1, $t1, -48  #converts t1's ascii value to dec value
add $s2, $s2, $t1   #add dec value of t1 to sumtotal
addi $s1, $s1, -1   #decrement array address
lp:         #loop for all digits preceeding the LSB
mul $t3, $t3, $t0   #multiply power by 10
beq $s1, $s0, FIN   #exit if beginning of string is reached
lb $t1, ($s1)       #load char from array into t1
blt $t1, 48, error  #check if char is not a digit (ascii<'0')
bgt $t1, 57, error  #check if char is not a digit (ascii>'9')
addi $t1, $t1, -48  #converts t1's ascii value to dec value
mul $t1, $t1, $t3   #t1*10^(counter)
add $s2, $s2, $t1   #sumtotal=sumtotal+t1
addi $s1, $s1, -1   #decrement array address
j lp            #jump to start of loop

error:          #if non digit chars are entered, readInt returns 0
add $s2, $zero, $zero
j FIN

FIN:
li $v0, 1
add $a0, $s2, $zero
syscall 
li $v0, 10      #ends program
syscall

回答by sampath

mask the first four bits by anding the string with 0x0Flike this below

通过将字符串与0x0F下面这样的内容相加来屏蔽前四位

andi $t0,$t0,0x0F # where $t0 contains the ascii digit .

now $t0has the int of it.

现在$t0有了它的int。

回答by Michael

Assumes that $s1points to the beginning of a NULL-terminated string (i.e. to the most significant digit), $t0contains 10, and $s2contains 0:

假设$s1指向以 NULL 结尾的字符串的开头(即最高有效数字),$t0包含 10,并且$s2包含 0:

lp:         
  lbu $t1, ($s1)       #load unsigned char from array into t1
  beq $t1, ##代码##, FIN     #NULL terminator found
  blt $t1, 48, error   #check if char is not a digit (ascii<'0')
  bgt $t1, 57, error   #check if char is not a digit (ascii>'9')
  addi $t1, $t1, -48   #converts t1's ascii value to dec value
  mul $s2, $s2, $t0    #sum *= 10
  add $s2, $s2, $t1    #sum += array[s1]-'0'
  addi $s1, $s1, 1     #increment array address
  j lp                 #jump to start of loop

This has one mulless per iteration, and there's no need of knowing the length of the string before entering the loop.

mul每次迭代都会少一个,并且在进入循环之前不需要知道字符串的长度。