Mips Runtime exception at 0x00400258: address out of range 0x00000068

1

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
assembly
mips
procedure
mars-simulator
asked on Stack Overflow Feb 10, 2021 by Abdelrahman • edited Feb 10, 2021 by Abdelrahman

1 Answer

0

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.

answered on Stack Overflow Feb 11, 2021 by Erik Eidt

User contributions licensed under CC BY-SA 3.0