이 프로그램은 사용자가 제공 한 정확도로 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;
}
이
내 어셈블리 코드입니다 :; 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
샘플 출력 :
내가 사용 :
- NASM 버전 2.11.06에 컴파일 2014 년 10 월 20 일
- GCC (MinGW.org GCC-6.3.0-1) 6.3.0
컴파일과 어셈블러 명령 :
nasm -o pi.o -f coff pi.asm
gcc pi.o pi_interface.c -o projekt.exe -Wall -Wextra
정확도를 지정하는 것은 사용자에게 친숙하지 않습니다. 올바른 자릿수가 더 많이 기대됩니다. – molbdnilo
어떤 방식으로 올바르게 작동하지 않는지 설명하십시오. – molbdnilo
다음과 같은 경우 프로그램이 올바르게 작동하지 않습니다. calculate_pi() 함수는 arctg (1)에 대한 테일러 공식으로 pi를 계산합니다. 이 행이 주석을하면 함수에 아주 작은 값이 전송되고 프로그램이 무한히 실행됩니다. – LeoProXXX