Сборка x86 x87 Numeric Proccesor

Я пытаюсь написать цикл в сборке, которая эквивалентна:

for(i=0; x1 + i*h <= x2; i++)

И каждый раз, когда я вызываю другую функцию, которая использует (x1 + i*h) в качестве одного из своих параметров, по какой-то причине она получает ее с добавлением 0,00000000000000001. Например, если я отправлю 0,26, он получит 0,26000000000000001 вместо этого, что приведет к сбою программы.

Вот часть C программы:

#include <stdio.h>
#include <math.h>

extern double find_delta1(double(*f)(double), double x0, double eps);
extern double find_delta2(double(*f)(double), double x1, double x2, double h, double eps);

double mysqr(double x)
{
    return x*x;
} // mysqr

int main()
{
    double x1 = -0.5, x2 = 1.0, x, eps = 0.001, h = 0.01;

    x = (x1 + x2) / 2.0;
    printf("\nfind_delta1(mysqr,%lf, %lf) = %lf\n", x, eps, find_delta1(mysqr, x, eps));
    printf("\nfind_delta2(mysqr, %lf, %lf,%lf, %lf) = %lf\n", x, x2, h, eps, find_delta2(mysqr, x, x2, h, eps));

    return 0;
} // main

А вот и сборочная часть:

.MODEL SMALL
.DATA
    DELTA       DQ  ?
    CURRENTX    DQ  ?
    TEMP        DQ  ?
    MIN         DQ  ?
    X           DQ  ?
    I           DW  ?
    TWO         DQ  2.0
.CODE
.386
.387
;double find_delta1(double (*f)(double),double x0, double eps)
;                       +4                  +6          +14

PUBLIC _find_delta1
_find_delta1 PROC NEAR

PUSH BP
MOV BP,SP

FLDZ        ;
FST X       ;
FSTP DELTA  ; Initialize parameters

FLD QWORD PTR [BP+6]    ;
FABS                    ;
FSTP DELTA              ; Delta = |X0|

LOOP1:
FLD DELTA
FDIV TWO                ;
FST DELTA               ;   Delta = Delta / 2.0
FLD QWORD PTR [BP+6]    ;
FADD                    ;
FSTP X                  ;  X = X0 + Delta

PUSH X                  ;
CALL WORD PTR [BP+4]    ;
ADD SP,8                ;  ST(0) = f(X)

PUSH QWORD PTR [BP+6]   ;
CALL WORD PTR [BP+4]    ;
ADD SP,8                ;  ST(0) = f(X0)

FSUB        ;
FABS        ;   ST(0) = |f(X) - f(X0)|

FCOMP QWORD PTR [BP+14]     ;
FSTSW AX                    ;
SAHF                        ;   Compare with epsilon
JNB LOOP1

FLD DELTA       ; Return Delta

POP BP
RET
_find_delta1 ENDP
;----------------------------------------------------------------------------------------------------------------------------


;----------------------------------------------------------------------------------------------------------------------------

;double find_delta2(double (*f)(double),double x1, double x2, double h, double eps)
;                           +4              +6          +14     +22         +30

PUBLIC _find_delta2
_find_delta2 PROC NEAR

PUSH BP
MOV BP,SP

MOV I,0
FLDZ            ;
FST TEMP        ;
FST CURRENTX    ;
FSTP MIN        ; Initialize parameters

PUSH QWORD PTR [BP+30]  ;
PUSH QWORD PTR [BP+6]   ;
PUSH WORD PTR [BP+4]    ;
CALL _find_delta1       ;
ADD SP,20               ;   MIN = find_delta1(mysqr, X1, eps)

FSTP MIN

LOOP2:
FLD QWORD PTR [BP+6]    ; ST(0) = X1
FLD QWORD PTR [BP+22]   ; ST(0) = h
FIMUL I                 ; ST(0) = I*h
FADD                    ; ST(0) = X1 + I*h
FSTP CURRENTX

PUSH QWORD PTR [BP+30]  ;
PUSH CURRENTX           ;
PUSH WORD PTR [BP+4]    ;
CALL _find_delta1       ;
ADD SP,20               ;   ST(0) = find_delta1(mysqr, X1 + I*h, eps)

FCOM MIN            ;
FSTSW AX            ;
SAHF                ;
JNB NOTBELOW        ;   Compare with current minimum

FSTP MIN            ;   If (find_delta1(mysqr, X1 + I*h, eps) < MIN)
INC I               ;   -> MIN = find_delta1(mysqr, X1 + I*h, eps)
JMP SHORT NEXT      ;       i++

NOTBELOW:           ;   Else
FSTP TEMP           ;   -> i++
INC I               ;

NEXT:
FLD CURRENTX
FCOMP QWORD PTR [BP+14] ;
FSTSW AX                ;
SAHF                    ;
JNE LOOP2               ; Compare (X1 + I*h) with X2


FLD MIN

POP BP
RET
_find_delta2 ENDP
END

Проблема возникает во второй итерации LOOP2, так как в первый раз I*h = 0, следовательно, никакие изменения не применяются к x1.

Если кто-то может сказать мне, что я делаю неправильно, я был бы очень благодарен.

0 ответов

Другие вопросы по тегам