我已经低于这个程序了,由于某些原因我无法找到我的程序集常常卡住。
我已经检查了SP
,并且代码返回到它应该的正确位置,并且堆栈始终是应该的。
我做过的一件事就是让常规没有被卡住的是将跳转更改为JNL
,其他任何跳跃都会卡住。
这是我在C和汇编中的代码。最后有一个C代码,显示汇编例程应该做什么。
#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
这就是ASM应该做的事情:
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和F2:
double f1 (double x, double y)
{
return sin (x+y);
}
double f2 (double x, double y)
{
return cos (x+y);
}
答案 0 :(得分:2)
FCOMPP
仅设置FPU中的条件代码位。您可能需要FCOMIP
(如果需要,可以使用另一个弹出窗口),以便您可以使用条件分支指令。
即使你说你检查了SP
,也要注意典型的C调用约定允许修改DX
,所以假设它没有改变它是不安全的。您应该在ADD SP,DX
之前重新加载元素计数。
更新:好的,我已经开始工作了(虽然我不知道结果是否正确:x = 0.9516和y = 0.3072)。您应该使用JB
而不是JL
,因为根据结果由C0
设置的FPU标志位C3
和FCOMPP
- 将被转移到分别是CF
和ZF
,但JL
检查SF
和OF
这些没有意义。
附注:如果使用DWORD PTR
,则代码不是纯16位,只能在32位处理器上运行。
当然,你的程序可以简化很多。