将字符串转换为数字

时间:2019-03-24 16:18:38

标签: assembly mips

# 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)正在破坏原始地址。

如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

区分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