1

main.c で呼び出される関数をアセンブリに実装するプロジェクトに取り組んでいます。C の署名関数宣言はvoid strrev(char *str) ; 、Ret 命令によって不正な命令エラーが発生します。なんで?これは初めてのことです。

関連するコードのみを投稿しようとしています:

SECTION .text
        global strrev

strrev:
        push    ebp
        mov     ebp, esp

        push    esi
        push    edi
        push    ebx

// doing things with al, bl, ecx, edi, and esi registers here


// restore registers and return    
        mov     esp,    ebp
        pop     ebx
        pop     edi
        pop     esi
        pop     ebp

        ret

エラー:

(gdb)
Program received signal SIGILL, Illegal instruction.
0xbffff49a in ?? ()

この方法でコンパイルおよびリンクします。

nasm -f elf -g strrepl.asm
nasm -f elf -g strrev.asm
gcc -Wall -g -c main7.c
gcc -Wall -g strrepl.o strrev.o main7.o
4

1 に答える 1

4

mov esp, ebpespが実行されたときの場所を指すように変更mov ebp, espされます。esiedi、およびをスタックにプッシュする前だったebxので、それらをポップすることはできなくなりました。あなたがそうしているので、スタックが間違っていて、ret期待どおりに機能しません。

命令を削除できる可能性がありmov esp, ebpます。このようなスタック ポインターの復元は、ルーチン内のスタック ポインターに変数の変更がある場合にのみ必要です (たとえば、スタックを目的の位置合わせに移動するため、または可変長配列用のスペースを作成するため)。スタックが単純に処理される場合は、プッシュした順序とは逆の順序でポップするだけです。スタックに変数の変更がある場合は、保存した ではなく、別の場所にポインターを復元して、 、、およびebpをポップできるようにする必要があります。ebxediesi

于 2013-04-12T18:01:06.233 に答える