2

マージ ソート アルゴリズムを実装する MIPS サブルーチンを作成しました (コードは記事の最後にあります)。配列へのポインタとそのサイズを受け取ります。ソートし、何も返さないでください。

私はそれをデバッグし、いくつかのエラーを修正しました。サブルーチンは基本ケース (サイズ 1 の配列) に達するまではうまく機能しているように見えるので、現在、gdb とこの C コードを使用して、その特定の状況でデバッグしています:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

extern void merge_sort(char*, int);

int main(int argc,char **argv){

    char* vector;
    vector = (char*)malloc(sizeof(char));
    if(vector == NULL) printf("error");

    size_t vector_size = 1;
    memcpy(vector,"5",vector_size);

    merge_sort(vector, vector_size);

    int i;
    for(i = 0; i < vector_size; i++){
            printf("%c ", vector[i]);
    }

    printf("\n");
    return 0;
}

私の問題は、サブルーチン行をステップ実行しているときに、最後から 2 番目の行 (jr ra) に到達するとクラッシュしてコード 060 で終了し、gdb が次のメッセージを表示することです。

Warning: GDB can't find the start of the function at 0x400730.
    GDB is unable to find the start of the function at 0x400730
    and thus can't determine the size of that function's stack 
    frame. This means that GDB may be unable to access that stack
    frame, or the frames below it.

    This problem is most likely caused by an invalid program 
    counter or stack pointer.  However, if you think GDB should
    simply search farther back from 0x400730 for code which looks
    like the beginning of a function, you can increase the range 
    of the search using the `set heuristic-fence-post' command. 
0x004008a0 in _start

なぜそれが起こるのか分かりません。に格納されているアドレスの問題か、スタック割り当ての誤りか、C と MIPS コードの間のリンケージが間違っている可能性があると思いますが、ra何が間違っているのかわかりません。

以下は、merge_sort の MIPS コードです。
基本ケースでは、コードは の行まで実行されbeq t1, zero, SALIDA、次に にジャンプしSALIDAて終了します。そのため、コードのその部分を貼り付けるだけです (SALIDA はスペイン語で終了を意味します:P)。

#include <mips/regdef.h>
#include <sys/syscall.h>

#define     SSIZE   (56)
#define     O_RA    (48)
#define     O_FP    (44)
#define     O_GP    (40)
#define     O_S3    (36)
#define     O_S2    (32)
#define     O_S1    (28)
#define     O_S0    (24)
#define     O_ARG0  (SSIZE)
#define     O_ARG1  ((SSIZE) + 4)

.text
.align  2
.globl  merge_sort
.ent    merge_sort

merge_sort:
.frame $fp, SSIZE, ra
.set noreorder
.cpload t9
.set reorder     

subu    sp,sp,SSIZE

sw  s0, O_S0(sp)
sw  s1, O_S1(sp)
sw  s2, O_S2(sp)
sw  s3, O_S3(sp)

sw  gp, O_GP(sp)
sw  $fp, O_FP(sp)
sw  ra, O_RA(sp) 
move    $fp, sp

sw  a0, O_ARG0($fp)
sw  a1, O_ARG1($fp)

lw  t0, O_ARG1($fp)
addi    t1, t0, -1

beq     t1, zero, SALIDA

SALIDA:     
lw  s0, O_S0($fp)
lw  s1, O_S1($fp)
lw  s2, O_S2($fp)
lw  s3, O_S3($fp)

move    sp, $fp
lw  gp, O_GP($fp)
lw  $fp, O_FP($fp)
lw  ra, O_RA($fp) 

addiu   sp, sp, SSIZE

jr  ra

.end    merge_sort
4

1 に答える 1

3

あなたの問題は、サブルーチンの終わり近くにある次のとおりだと思います。

lw  $fp, O_FP($fp)    // restores $fp
lw  ra, O_RA($fp)     // restore ra, but $fp isn't pointing to our frame anymore

これらの指示を逆にすると、よりうまくいくかもしれないと思います。

于 2012-05-02T01:03:57.613 に答える