このプログラムは、ユーザーが提供する精度でpiを計算する必要があります。 calculate_pi()関数はNASMで記述されています。asm関数を呼び出す前にCでprintfを呼び出すかどうかの不思議な副作用はありますか?
//printf("accuracy: %.15f\n", precision); //<- This line
プログラムが正しく動作しません。この行がコメント化されている場合は、なぜ は、誰かが私に説明できます。 calcuta_pi()関数に奇妙な数字を送りますか?この行がコメントされている場合、関数には非常に小さな値が送られ、プログラムは無限に実行されます。
しかし、コメントされていないプログラムが正しく動作するかどうか。
#include <stdio.h>
#include <math.h>
extern double calculate_pi(double precision); /* external function declaration */
double calculate_pi(double precision); /* function prototype */
int main()
{
double precision = 1;
printf("A program that calculates pi, with accuracy provided by the user\n");
printf("Give me accuracy\n");
while(1)
{
if (scanf("%lf", &precision) != 1)
{
printf("reading error\n");
fseek(stdin,0,SEEK_END);
continue;
}
if(precision<0)
precision = fabs(precision);
//printf("accuracy: %.15f\n", precision); //<- This line
printf("pi: %.15f\n", calculate_pi(precision));
}
return 0;
}
これは私のアセンブリコードです:私が使用している
:
- NASMバージョン2.11.06を上にコンパイル
; arctg(1)=a ; tg(arctg(1))=tg(a) ; atan(x) = x - x^3/3 + x^5/5 - x^7/7 + x^9/9.. ; PI/4 = atan(1) = 1 - 1/3 + 1/5 - 1/7 + 1/9... ; PI = (4/1) - (4/3) + (4/5) - (4/7) + (4/9) - (4/11) + (4/13) - (4/15) ... section .text use32 global _calculate_pi _calculate_pi: %idefine a [ebp+12] ;ramka stosu push ebp mov ebp, esp ;ustawianie zmiennych fld qword [const_wynik] fstp qword [wynik] fld qword [const_licznik] fstp qword [licznik] fld qword [const_mianownik] fstp qword [mianownik] .loop: finit ; inicjalizacja stosu FPU fld qword [licznik] ;licznik na stos fld qword [mianownik] ;mianownik na stos fdiv ;wynik dzielenia st1/st0 fadd qword [wynik] ;st0 = wynik dzielenia + [wynik] fstp qword [wynik] ;wywalamy z st0 do [wynik] ;zmieniamy mianownik + 2 fld qword [mianownik] ;mianownik na stos fadd qword [zwiekszmian] ;st0 = mianownik + 2 fstp qword [mianownik] ;wywalamy z st0 do [mianownik] ;zmieniamy licznik *(-1) fld qword [licznik] ;licznik na stos fchs ;st0 = -st0 = -licznik fstp qword [licznik] ;wywalamy z st0 do [licznik] ;sprawdzanie dokladnosci fld qword[wynik] ;wynik na stos fldpi ;pi na stos fsub ;st0 = wynik-pi = st1 - st0 fabs ;st0 = |wynik-pi| fld qword a ;st0 = zadana dokladnosc ;(Unordered Compare ST(0) to ST(i) and set CPU flags and Pop ST(0)) ;Przyrostek p oznacza obniżenie stosu rejestrów koprocesora, przyrostek i oznacza zapisywanie wyników bezpośrednio do flag procesora a nie flag koprocesora fucomip st0, st1 ;porownanie z dokladnoscia if(zadana dokladnosc > uzyskana) jb .loop ;only the C0 bit (CF flag) would be set if no error fld qword [wynik] ;zwraca to co w st0 leave ; LEAVE = mov esp, ebp/pop ebp ret section .data: wynik dq 4.0 licznik dq -4.0 mianownik dq 3.0 zwiekszmian dq 2.0 const_wynik dq 4.0 const_licznik dq -4.0 const_mianownik dq 3.0
サンプル出力2014年10月20日
- のgcc(GCC MinGW.org-6.3.0-1)6.3.0
コンパイルとアセンブラのコマンド:
これは非常にユーザーフレンドリーな精度の指定方法ではありません。正しい桁数が予想されます。 – molbdnilo
どのように正しく動作しないか説明してください。 – molbdnilo
次の場合、プログラムは正しく動作しません。 calculate_pi()関数は、arctg(1)のテイラー式でpiを計算します。 この行がコメントすると、関数には非常に小さな値が送信され、プログラムは無限に実行されます。 – LeoProXXX