2016-03-29 7 views
1

こんにちは、gccコンパイラを使用してアセンブリ言語を初めて使用しています。現在、私は関数を扱っています。 私のプログラムがレジスタeaxebxecx及びedxにこれらの値を格納する、4つのint値をユーザに要求し、次いで、(ebx/eax)分割する関数を呼び出します。私はidivが残渣を保存するためにedxを使用することを理解しているので、除算後に "d"の値を保存します。次に、(eax-ecx)を減算し、(eax*edx)を掛けて、レジスタeaxの内部の値を返します。何らかの理由で私は、セグメンテーションフォールトを得る:ここでは11 は私のコードです:セグメンテーションフォールト:11アセンブリOSX

#include <stdio.h> 

int a, b, c, d; 

int main (void) 
{ 
    printf("Dame a: "); 
    scanf("%d", &a); 
    printf("Dame b: "); 
    scanf("%d", &b); 

    printf("Dame c: "); 
    scanf("%d", &c); 

    printf("Dame d: "); 
    scanf("%d", &d); 

    __asm( ".intel_syntax noprefix;" 
       "xor eax, eax;" 
       "mov eax, dword ptr [_a];" 
       "xor ebx, ebx;" 
       "mov ebx, dword ptr [_b];" 
       "xor ecx, ecx;" 
       "mov ecx, dword ptr [_c];" 
       "Call fun1;" 
       "mov dword ptr [_a], eax;" 


       "fun1: xor edx, edx;" 
       "idiv ebx;" 
       "sub eax, ecx;" 
       "mov edx, dword ptr [_d];" 
       "imul eax, edx;" 
       "ret;" 

       ".att_syntax"); 

    printf("%d\n", a); 
} 

は、いくつかのポインタエラーとは何かですか?

+0

Cコードから呼び出される関数はありません。これは誤って統合されたアセンブラコードのように見えます。これはどのように実行されると思いますか? C変数をアセンブラコードに正しく渡したり、clobbersをリストしたりしないでください。インラインアセンブラを使用する方法をお読みください。 – Olaf

+1

また、シンタックスをインラインasmで切り替えることは悪い考えです。 int構文をasmにするには 'gcc -masm = intel'を使います。 PS:あなたの実行が 'fun1'に落ち込み、' ret'が 'main'から終了します(あなたが運が良ければ、それ以外の場合はクラッシュします)。 – Jester

+0

こんにちはJesterさんが答えてくれてありがとうございました。インラインasmの構文を切り替えるのは悪い習慣です。なぜなら、32ビット絶対アドレス指定は64ビットモードエラーではサポートされていません。 –

答えて

2

は別として、他のエラーからのコメントで指摘し、あなたはここに大きな問題があります。

  "mov ecx, dword ptr [_c];" 
      "Call fun1;" 
      "mov dword ptr [_a], eax;" 


      "fun1: xor edx, edx;" 
      "idiv ebx;" 
      "sub eax, ecx;" 
      "mov edx, dword ptr [_d];" 
      "imul eax, edx;" 
      "ret;" 

は、プログラムの流れを考えてみましょう。あなたのCコードはこのアセンブリコードに入ります。アセンブリコードはそれ自身の内部関数を呼び出します(問題ではありません)。呼び出し前の命令に戻ります。問題はありません。値はEAXに移されます。そして関数に戻り値を返します。これはひどく悪いです。

これは、retになり、C関数のエピローグ全体をバイパスしています。これは、スタックが適切にクリーンアップされておらず、スタックが復元されていないことを意味します。これはほぼ確実にクラッシュにつながります。

関連する問題