将字符串转换为数字

Converting a string into numbers

# replacing all digits in a string with their complement in 9.
.data
    string: .asciiz "123471863"

.text
main:
    # load string's 1st address into the memory
    la $a0, string

    # initialize the loop-counter
    li $t0, 0
    li $t1, 9 # complement envelope for later use

    # start the loop    
start_loop: 
    lb $t2, ($a0) # Take one character from string

    # loop termination condition
    beq $t2, $zero, end_loop # terminate if null-value found

    subi $t2, $t2, 48 # convert it to a digit
    sub $t2, $t1, $t2 # apply complement to $t2
    sw $t2,($a0) # restore the string-byte content

    addi $a0, $a0, 1 # go to next string-byte
    addi $t0, $t0, 1 # increment loop-counter

    j start_loop
end_loop: 

    # print string  
    la $a0, string # load 1st address of the string
    li $v0, 4 # syscall for string print   
    syscall

    move $a0, $t0 # load 1st address of the string
    li $v0, 1 # syscall for string print   
    syscall

    # exit program
    li $v0, 10
    syscall

程序未按预期运行。第一次迭代后,$a0 寄存器未给出正确的值。显然,sw $t2,($a0) 正在破坏原始地址。

我该如何解决这个问题?

区分 null 和 '0' 没有问题。 null 为 0,而 '\0' 为 48.

你的测试

    beq $t2, $zero, end_loop # terminate if null-value found

完全正确,会检测到字符串的结尾。

你的算法不对。

在 C 中补数的一种方法是:

while(c=*str){
  c=c-'0' ; // transform the number to integer
  c=9-c;    // complement it
  c += '0'; // add 48 to turn it back to a character
  str++;
}

您缺少最后一次字符转换。

如果你改变

    sub $t2, $t1, $t2 # apply complement to $t2

    sub $t2, $t1, $t2 # apply complement to $t2
    addi $t2, $t2, 48

一切正常。

或者,您可以简化算法并说明计算 c=9-(c-48)+48 等同于 c=105-c。在start_loop

之前添加
   li $t4 105 ## 

并替换三行

    subi $t2, $t2, 48 # convert it to a digit
    sub $t2, $t1, $t2 # apply complement to $t2
    addi $t2, $t2, 48

来自

   sub $t2,$t4,$t2  # complement to 9 directly on char representing the digit