# 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)
正在破坏原始地址。
如何解决这个问题?
答案 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