I have below this program and for some reason that I can’t find my assembly routine gets stuck.
I already checked SP and that the code returns to the right place where it should and that the stack is always as it should.
There is only one thing I’ve done so that the routine didn’t get stuck was to change the jump to JNL, with any other jump it gets stuck.
This is my code in C and assembly. In the end there is a C code that shows what the assembly routine should do.
#include <stdio.h>
#include <math.h>
#include <conio.h>
extern void two_point (double (*f1)(double, double), double (*f2)(double, double), double x, double y, double *ptr1, double *ptr2);
extern void fixed2 (double (*f1)(double, double), double (*f2)(double, double), double x0, double y0, double *ptr1, double *ptr2, double eps);
double f1 (double x, double y);
double f2 (double x, double y);
int main()
{
double x, y;
fixed2 (f1, f2, 1.4, 1.4, &x, &y, 0.001);
printf ("x= %lf, y= %lf\n", x, y);
return 0;
}
double f1 (double x, double y)
{
return sin (x+y);
}
double f2 (double x, double y)
{
return cos (x+y);
}
ASM CODE:
;HW4a.asm
.MODEL SMALL
.DATA
x0 DQ ?
x1 DQ ?
y0 DQ ?
y1 DQ ?
x2 DQ ?
y2 DQ ?
element DW 16;double*2
.CODE
.386
.387
;two_point (double (*f1)(double, double), double (*f2)(double, double), double x, double y, double *ptr1, double *ptr2)
;f1=BP+4, f2=BP+6, x=BP+8, y=BP+16, ptr1=BP+24, ptr2=BP+26
_two_point PROC NEAR
PUSH BP
MOV BP,SP
PUSH SI
PUSH DI
MOV SI,WORD PTR[BP+24]
MOV DI,WORD PTR[BP+26]
FLD QWORD PTR [BP+16];ST0=Y
FSTP y2
FLD QWORD PTR [BP+8];ST0=X
FSTP x2
PUSH DWORD PTR y2+4
PUSH DWORD PTR y2
PUSH DWORD PTR x2+4
PUSH DWORD PTR x2
;f1:
CALL [BP+4];CALL F1
FSTP QWORD PTR [SI];SI GET RETURNED VALUE FROM F1
MOV [BP+24],SI;PTR1=F1(X,Y)
;f2:
CALL [BP+6];CALL F2
FSTP QWORD PTR [DI];DI GET RETURNED VALUE FROM F2
MOV [BP+26],DI;PTR2=F2(X,Y)
;end:
ADD SP,element
POP DI
POP SI
POP BP
RET
_two_point ENDP
;fixed2 (double (*f1)(double, double), double (*f2)(double, double), double x0, double y0, double *ptr1, double *ptr2, double eps)
;f1=BP+4, f2=BP+6, x0=BP+8, y0=BP+16, ptr1=BP+24, ptr2=BP+26, eps=BP+28
PUBLIC _fixed2
_fixed2 PROC NEAR
PUSH BP
MOV BP,SP
;pre loop:
PUSH SI
PUSH DI
MOV SI,WORD PTR[BP+24];SI=&ptr1
MOV DI,WORD PTR[BP+26];DI=&ptr2
FLD QWORD PTR [BP+16];ST0=Y
FST y0
FSTP y1
FLD QWORD PTR [BP+8];ST0=X
FST x0
FSTP x1
LOOPER:
FLD y1
FST y0;y0=y1
FSTP QWORD PTR [DI];SI=&y1
PUSH WORD PTR DI;push &y1
FLD x1
FST x0;x0=x1
FSTP QWORD PTR [SI];SI=&x1
PUSH WORD PTR SI;push &x1
PUSH DWORD PTR y0+4
PUSH DWORD PTR y0
PUSH DWORD PTR x0+4
PUSH DWORD PTR x0
PUSH WORD PTR [BP+6];push f2
PUSH WORD PTR [BP+4];push f1
CALL _two_point
MOV DI,WORD PTR [BP-6];DI=&y0
MOV SI,WORD PTR [BP-8];SI=&x0
ADD SP,8;sizeof(f1+f2)+sizeof(*ptr1+*ptr2)
ADD SP,element
FLD QWORD PTR [SI];load x1
FST x1
FLD x0
FSUB
FABS;|x1-x0|
FLD QWORD PTR [DI];load y1
FST y1
FLD y0
FSUB
FABS;|y1-y0|
FADD;ST[0]=|y1-y0|+|x1-x0|
FLD QWORD PTR [BP+28];ST[0]=eps
FCOMPP;ST[0]-ST[1]
FSTSW AX
SAHF
JBE LOOPER;while ((fabs(x1-x0) + fabs(y1-y0))>=eps)
;end:
FLD x1
FSTP QWORD PTR [SI]
MOV WORD PTR [BP+24],SI;update *ptr1=x1
FLD y1
FSTP QWORD PTR [DI]
MOV WORD PTR [BP+26],DI;update *ptr2=y1
POP DI
POP SI
POP BP
RET
_fixed2 ENDP
END
and this is what the ASM SHOULD DO:
void fixed2 (double (*f1)(double, double), double (*f2)(double, double), double x0, double y0, double *ptr1, double *ptr2, double eps)
{
double x1= x0, y1= y0;
do
{
x0= x1;
y0= y1;
two_point (f1, f2, x0, y0, &x1, &y1);
} while ((fabs(x1-x0) + fabs(y1-y0))>=eps);
*ptr1 = x1;
*ptr2 = y1;
}
F1 and F2:
double f1 (double x, double y)
{
return sin (x+y);
}
double f2 (double x, double y)
{
return cos (x+y);
}
FCOMPPonly sets the condition code bits in the FPU. You probably meantFCOMIP(followed by another pop if required) so that you can use the conditional branch instructions.Also even though you said you checked
SPbe advised that typical C calling conventions allow forDXto be modified, so it’s not safe assuming it’s unchanged. You should reload the element count before theADD SP,DX.Update: Okay, I have gotten it to work (although I don’t know if the result is correct: x=0.9516 and y=0.3072). You should be using
JBnotJLbecause the FPU flag bitsC0andC3– that were set byFCOMPPaccording to the result – will be transferred toCFandZFrespectively, butJLchecksSFandOFwhich are not meaningful here.Side note: if you use
DWORD PTRyour code isn’t pure 16 bit and it will only run on 32 bit processors.Of course your program could be simplified a lot.