0x00400258 处的 Mips 运行时异常:地址超出范围 0x00000068

问题描述

我正在尝试在 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] 作为参数传递,这只是一个地址计算——不涉及对内存的取消引用。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...