问题描述
我正在尝试在 mips 中实现 word occurance counter in a string program
,每当我调用 strcmp 函数时,我都会收到错误 Runtime exception at 0x00400258: address out of range 0x00000068
我真的不明白为什么,因为我对下面的 mips 还是新手,我将提供c 代码和完整的 mips 代码,以便对查看者尽可能简单。
预期的输入字符串例如:hello world hello
预期输出 hello - 2
world - 1
the strcmp function
strcmp:
addi $sp,$sp,-4
sw $ra 0($sp)
addi $t0,$0,0
add $t1,$a2 # pass argument a2 to $t1
add $t2,$a3 # pass argument a3 to $t2
L6:
lb $t3,($t1) #load a byte from each string
lb $t4,($t2)
beqz $t3,T4Check #str1 end
beqz $t4,missmatch
subu $t5,$t3,$t4 #compare two bytes
bnez $t5,missmatch
addi $t1,$t1,1 #t1 points to the next byte of str1
addi $t2,$t2,1
j L6
missmatch:
addi $v0,1
j finish2
T4Check:
bnez $t4,missmatch
addi $v0,0
finish2:
lw $ra,0($sp) # restore old $sp
addi $sp,4
jr $ra
the function call part
Else:
add $t8,$s7 # add base ptr1 to offset j
lb $a2,($t8) # $a2 = ptr1[j]
add $t6,$t0,$s6 # add base p to offset i
lb $a3,($t6) # $a3 = p[i]
jal strcmp # jump strcmp
My full C code
#include <stdio.h>
#include <string.h>
int my_strcmp(char *strg1,char *strg2){
while( ( *strg1 != '\0' && *strg2 != '\0' ) && *strg1 == *strg2 )
{
strg1++;
strg2++;
}
if(*strg1 == *strg2)
{
return 0; // strings are identical
}
else
{
return *strg1 - *strg2;
}
}
void new_strcpy(char x[],char y[]){
int i=0;
while((x[i]=y[i])!=0){
i++;
}
}
int my_strlen(char str[]){
int len=0,i=0;
while(str[i]!='\0'){
i++;
len++;
}
return len;
}
void word_statistics(char str[]){
int count = 0,c = 0,i,j = 0,k,space = 0;
char p[100][100],ptr1[100][100];
printf("string length is %d\n",my_strlen(str));
i=0;
while(i<my_strlen(str))
{
if (str[i] == ' ')
{
space++;
}
i++;
}
i=0;
j=0;
k=0;
while(j < my_strlen(str))
{
if (str[j] == ' ')
{
p[i][k] = '\0';
i++;
k = 0;
}
else
{
p[i][k++] = str[j];
}
j++;
}
k=0;
i=0;
while(i <= space)
{ j=0;
while(j <= space)
{
if (i == j)
{
j++;
new_strcpy(ptr1[k],p[i]);
k++;
count++;
break;
}
else
{
if (my_strcmp(ptr1[j],p[i]) != 0){
j++;
continue;
}
else{
j++;
break;
}
}
}
i++;
}
printf("%d",count);
i=0;
while(i < count)
{
j=0;
while(j <= space)
{
if (my_strcmp(ptr1[i],p[j]) == 0)
c++;
j++;
}
printf(" %s : %d \n",ptr1[i],c);
c = 0;
i++;
}
}
int main(){
char str[100];
printf("Enter the string\n");
scanf(" %[^\n]s",str);
word_statistics(str);
return 0;
}
My full mips code
.data
msg: .asciiz "Enter a string \n"
str: .space 30 # get the paragraph from the user
ptr1 : .space 400 #ptr1[20][20]
p: .space 400 #p[20][20]
stringlen: .asciiz "String length is "
blankSpace: .ascii " "
next: .asciiz "\n Next while"
.text
main:
jal word_stat
word_stat:
addi $sp,-4
sw $ra 0($sp)
li $v0,4
la $a0,msg
syscall # printing the message to the user
li $v0,8
la $a0,str
li $a1,30
syscall # getting a paragraph from the user
li $v0,4
la $a0,stringlen #"String length is "
syscall
la $a0,str
jal strlen
addi $a0,$v0,0
addi $s3,$a0,0 #strlen value $s3
li $v0,1
syscall # calling the strlen function to count the string length
la $a3,blankSpace
lb $s4,0($a3) # $s4 =blankspace
addi $s2,0 # space =0
addi $t0,0 # i=0
la $a1,str
while1:
slt $t5,$s3 #set $t5=1 if i < strlength
beq $t5,L5 #if i>strlength
add $t6,$a1,$t0 # $a0 = str[]
lbu $t6,0($t6) # str[i]
beq $t6,$s4,L2 #if str[i]==' ' branch
L3:
addi $t0,1 # i++
j while1
L2:
addi $s2,$s2,1 # space ++ if str[i]==' '
j L3
L5:
la,$a2,p
la $s5,str # address start of str
la $s6,p # address start of p
la $s7,ptr1 # address start of ptrl
li $t9,20 # width =20
li $t0,0 # i=0
li $t2,0 # j=0
li $t3,0 # k=0
WHILE:
bge $t2,$s3,End_While # branch if j<=strlength
add $t5,$s5
lb $t7,($t5) # $t7 = str[j]
beq $t7,L # if str[j]== ' ' branch L
mul $t8,$t9,$t0 # width *i
add $t8,$t8,$t3 # width * i+k
add $t8,$s6 # base array (width *i+k)
sb $t7,($t8) # p[i][k++]=str[j]
addi $t3,1 # k++
L10:
addi $t2,1 # j++
j WHILE
L:
mul $t8,$t0 # array width * i
add $t8,$s6 # base array +(width * i+k)
sb $zero,($t8) # p[i][k++]='\0'
addi $t0,1 # i++
addi $t3,$zero,0 # k=0
j L10
End_While:
li $t0,0 # i=0
li $s0,0 # count=0
li $t3,0 # k=0
la $s6,p # address start of p
la $s7,ptr1 # address start of ptrl
While2:
slt $t4,$t0 # set $t4=1 if i>space
beq $t4,1,End_While2 # End While loop if i>space
addi $t2,0 # j=o
While3:
slt $t4,$t2 # set $t4=1 if j>space
beq $t4,End_While3 # End while loop if j > space
bne $t0,Else # if i==j
add $t8,$s7 # $t8 = add base address of ptr1 to offset k
lb $a2,($t8) # a2=ptr1[k]
add $t6,$s6 # t6 = add base address of p to offset i
lb $a3,($t6) # a3 = p[i]
jal strcpy # jump strcmp function
addi $t3,1 # k++
addi $s0,$s0,1 # count ++
addi $t2,1 # j++
j End_While3 # break
Else:
add $t8,($t6) # $a3 = p[i]
jal strcmp # jump strcmp
move $t5,$v0 # move v0 value to t5
beq $t5,Else2 # if strcmp(ptr1[j],p[i]!=0) branch else2
addi $t2,1 # j++
j While3 # continue
Else2:
addi $t2,1 # j++
j End_While3 # break
j While3
End_While3:
addi $t0,1 # i++
j While2
End_While2:
li $t0,0 # i=0
li $t3,0 # c=0
While5:
bge $t0,End_While5 # End loop if i >= count
li $t2,0 # j=0
While6:
slt $t5,$t2 # set t5=1 if j > space
beq $t5,End_while6 # End loop if j > space
add $t7,$s7 # base address of ptr1 + offset i
lb $a2,($t7) # a2 = ptr1[i]
add $t8,$s6 # add base address p to offset j
lb $a3,($t8) # a3 =p[j]
j strcmp
move $t6,$v0 # return of function strcmp
bne $t6,Loo # if strcmp != 0
addi $t3,1 # c++
Loo:
addi $t2,1 # j++
j While6
End_while6:
li $v0,4
move $a0,$a2
syscall # print(ptr1[i]) word to count
li $v0,1
move $a0,$t3
syscall # print c (word count number)
addi $t3,0 # c=0
addi $t0,1 # i++
j While5
End_While5:
li $v0,4
la $a0,next
syscall
li $v0,10
syscall # Exit terminating the program
lw $ra,0($sp) # restore old $sp
addi $sp,4
jr $ra
strcmp:
addi $sp,4
jr $ra
strcpy:
addi $sp,0 # i=0
L1:
add $t1,$s6,$t0 # address of y[i]
lb $t2,($t1) # load byte y[i] in $t2
add $t3,$s7,$t0 # similar address for x[i]
sb $t2,($t3) # store byte y[i] into x[i]
addi $t0,1 # i++
bne $t2,L1 # if y[i]!=0 go to L1
lw $t0,0($sp) # restore old $s0
addi $sp,4
jr $ra
strlen:
addi $sp,-4
sw $ra,0($sp)
addi $t0,0 # i=0
addi $t1,0 # len=0
l:
add $t2,$t0 # add base address to offset
lbu $t3,0($t2) # load base unsigned for char array
beq $t3,finish # if value of array[i] = '\0'
addi $t0,1 # i++
addi $t1,1 # len++
j l
finish:
subi $t1,1
add $v0,$0
lw $ra,4
jr $ra
解决方法
让我们看看你的一些 C 代码:
char p[100][100],ptr1[100][100];
...new_strcpy(ptr1[k],p[i])...
...my_strcmp(p[i],ptr1[j])...
这些数组是二维数组。但是二维数组,虽然需要两个 []
来访问一个字符元素,但只需要一个对内存的取消引用。
ptr1[k]
不是对内存的取消引用——它是一个地址计算:ptr1+k*100
并将类型从 char [][]
更改为 char []
,但不是在如下意义:这里没有进行内存访问,纯粹是在CPU内计算。
ptr1[k][i]
在汇编中会执行 ptr1+k*100+i
,然后将该地址取消引用 - 一次 - 以获取一个字符。
因此,将 ptr1[k]
作为参数传递,这只是一个地址计算——不涉及对内存的取消引用。