I am trying to implement a word occurance counter in a string program
in mips and whenever I call the strcmp function I get the error Runtime exception at 0x00400258: address out of range 0x00000068
I really don't understand why as I am still new to mips below I will provide the c code and the full mips code in order to be as simple as posible for the viewer .
expected input string ex: hello world hello
expected output hello - 2
world - 1
the strcmp function
strcmp:
addi $sp,$sp,-4
sw $ra 0($sp)
addi $t0,$0,0
add $t1,$0,$a2 # pass argument a2 to $t1
add $t2,$0,$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,$0,1
j finish2
T4Check:
bnez $t4,missmatch
addi $v0,$0,0
finish2:
lw $ra,0($sp) # restore old $sp
addi $sp,$sp,4
jr $ra
the function call part
Else:
add $t8,$t2,$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,$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,0 # space =0
addi $t0,$0,0 # i=0
la $a1,str
while1:
slt $t5,$t0,$s3 #set $t5=1 if i < strlength
beq $t5,$0,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,$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,$t2,$s5
lb $t7,($t5) # $t7 = str[j]
beq $t7,$s4,L # if str[j]== ' ' branch L
mul $t8,$t9,$t0 # width *i
add $t8,$t8,$t3 # width * i+k
add $t8,$t8,$s6 # base array (width *i+k)
sb $t7,($t8) # p[i][k++]=str[j]
addi $t3,$t3,1 # k++
L10:
addi $t2,$t2,1 # j++
j WHILE
L:
mul $t8,$t9,$t0 # array width * i
add $t8,$t8,$t3 # width * i+k
add $t8,$t8,$s6 # base array +(width * i+k)
sb $zero,($t8) # p[i][k++]='\0'
addi $t0,$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,$s2,$t0 # set $t4=1 if i>space
beq $t4,1,End_While2 # End While loop if i>space
addi $t2,$zero,0 # j=o
While3:
slt $t4,$s2,$t2 # set $t4=1 if j>space
beq $t4,1,End_While3 # End while loop if j > space
bne $t0,$t2,Else # if i==j
add $t8,$t3,$s7 # $t8 = add base address of ptr1 to offset k
lb $a2,($t8) # a2=ptr1[k]
add $t6,$t0,$s6 # t6 = add base address of p to offset i
lb $a3,($t6) # a3 = p[i]
jal strcpy # jump strcmp function
addi $t3,$t3,1 # k++
addi $s0,$s0,1 # count ++
addi $t2,$t2,1 # j++
j End_While3 # break
Else:
add $t8,$t2,$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
move $t5,$v0 # move v0 value to t5
beq $t5,$zero,Else2 # if strcmp(ptr1[j],p[i]!=0) branch else2
addi $t2,$t2,1 # j++
j While3 # continue
Else2:
addi $t2,$t2,1 # j++
j End_While3 # break
j While3
End_While3:
addi $t0,$t0,1 # i++
j While2
End_While2:
li $t0,0 # i=0
li $t3,0 # c=0
While5:
bge $t0,$s0,End_While5 # End loop if i >= count
li $t2,0 # j=0
While6:
slt $t5,$s2,$t2 # set t5=1 if j > space
beq $t5,1,End_while6 # End loop if j > space
add $t7,$t0,$s7 # base address of ptr1 + offset i
lb $a2,($t7) # a2 = ptr1[i]
add $t8,$t2,$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,0,Loo # if strcmp != 0
addi $t3,$t3,1 # c++
Loo:
addi $t2,$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,$zero,0 # c=0
addi $t0,$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,$sp,4
jr $ra
strcmp:
addi $sp,$sp,-4
sw $ra 0($sp)
addi $t0,$0,0
add $t1,$0,$a2 # pass argument a2 to $t1
add $t2,$0,$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,$0,1
j finish2
T4Check:
bnez $t4,missmatch
addi $v0,$0,0
finish2:
lw $ra,0($sp) # restore old $sp
addi $sp,$sp,4
jr $ra
strcpy:
addi $sp,$sp,-4
sw $ra 0($sp)
addi $t0,$0,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,$t0,1 # i++
bne $t2,$0,L1 # if y[i]!=0 go to L1
lw $t0,0($sp) # restore old $s0
addi $sp,$sp,4
jr $ra
strlen:
addi $sp,$sp,-4
sw $ra,0($sp)
addi $t0,$0,0 # i=0
addi $t1,$0,0 # len=0
l:
add $t2,$a0,$t0 # add base address to offset
lbu $t3,0($t2) # load base unsigned for char array
beq $t3,$0,finish # if value of array[i] = '\0'
addi $t0,$t0,1 # i++
addi $t1,$t1,1 # len++
j l
finish:
subi $t1,$t1,1
add $v0,$t1,$0
lw $ra,0($sp) # restore old $sp
addi $sp,$sp,4
jr $ra
Let's take a look at some of your C code:
char p[100][100],ptr1[100][100];
...new_strcpy(ptr1[k], p[i])...
...my_strcmp(p[i],ptr1[j])...
These arrays are double dimensioned arrays. But double dimensioned arrays, while taking two []
's to get to a character element, only require one dereference to memory.
ptr1[k]
is not a dereference to memory — it is an address computation: ptr1+k*100
and it changes the type to from char [][]
to char []
, but not a dereference in following sense: there is no memory access done by this, it is purely an in-CPU calculation.
ptr1[k][i]
in assembly would do ptr1+k*100+i
, then that address dereferenced — once — to get a character.
Thus, to pass ptr1[k]
as a parameter, that is simply an address calculation — no dereference to memory involved.
User contributions licensed under CC BY-SA 3.0