查看网站上的主题,但我无法解决我的问题。我注意到程序中的代码是无限的,在QTSpim中,我看到所涉及的寄存器是$s0
,$s1
,$t2
和$t4
。
几个周期后,消息Exception occurred at PC
然后expection 7 Bad data address
。
这是代码,我无法弄清楚错误在哪里,我试着在没有程序的情况下编写它并且它完美地工作。
.data
string: .asciiz "Hello Simon"
string2: .asciiz ""
.text
.globl main
Delete_space:
addi $sp, $sp, -16
sw $s0, 0($sp)
sw $s1, 4($sp)
add $t8, $a0, $zero
lenght_string:
lb $t0, 0($t8)
beqz $t0, for #t8 contain the lenght of string
add $t8, 1
j lenght_string
for:
add $s0, $zero, $zero #i=0
add $s1, $zero, $zero #j=0
condition:
slt $t1, $s0, $t8 #i< lenght_string
beq $t1, $zero, endfor
consequence:
add $t2, $t8, $s0
lb $t3, 0($t2)
bne $t3, ' ', op1
beq $t3, ' ', else
addi $s0, $s0, 1
addi $s1, $s1, 1
j condition
op1:
add $t4, $a1, $s1
sb $t3, 0($t4)
addi $s0, $s0, 1
addi $s1, $s1, 1
j condition
else:
sub $s1, $s1, 1
addi $s0, $s0, 1
addi $s1, $s1, 1
j condition
endfor:
#end
lw $s1, 4($sp)
lw $s0, 0($sp)
addi $sp, $sp, 16
jr $ra
main:
la $a0, string
la $a1, string2
jal Delete_space
la $a0, string2
li $v0, 4
syscall
li $v0, 10
syscall
答案 0 :(得分:1)
我认为你试图将字符从一个字符串复制到另一个字符串,跳过空格。 (也许这不是你想要做的 - 不幸的是,我没有时间详细跟踪代码。)我认为问题是你从源字符串复制到没有的数据区域属于你。
在汇编语言中,字符串的处理方式与高级语言中的字符串不同。它们只是一个字节序列 - 没有一个String的概念可以自动扩展以包含你放入它的内容。并且没有边界检查的概念。
查看这些字符串声明:
.data
string: .asciiz "Hello Simon"
string2: .asciiz ""
您所做的是将string
分配给包含字节值'H'
的内存地址。后续内存位置包含'e', 'l', 'l', 'o', ' ', 'S', 'i', 'm', 'o', 'n', '\0'
。
然后,您已将string2
分配给包含字节值'\0'
(空终止符)的内存地址。
如果将一个字节写入string2
指向的内存地址,它将替换空终止符。 (此时你已经遇到了麻烦,因为syscall
不知道你的字符串结束的位置。)如果你再写一个字节到string2 + 1
所指向的内存地址,你现在就是写入您未分配给string2
的内存。它可能属于存储的其他变量 - 在这种情况下,您只需覆盖之前的变量。这是一个“缓冲区溢出”,这就是像Internet Explorer这样写得不好的程序如何被黑客利用。
如果我正确地解释了你的程序的目的,你需要为你的输出创建一个足以容纳它的缓冲区。假设您的输出永远不会超过您的输入,那么这样的东西就会起作用:
.data
string: .asciiz "Hello Simon"
string2: .asciiz "xxxxxxxxxxx"