2013-01-18 76 views
-2

我有这个程序下,由于某种原因,我找不到我的程序集卡住了。x86汇编程序无故卡住

我已经检查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); 
} 

汇编代码:

;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); 
} 
+1

要求他人发现代码中的错误并不富有成效。你应该在调试器中遍历你的代码;那么你会发现它在哪里“卡住”。 –

+0

相信我,我住在调试器中的最后3天,仍无法找到:( ,你可以看到我说,我检查SP,这意味着我不得不看到它在调试器 – shimon

+3

嗯,这绝对不是卡住不理由;不幸的是,你需要调试才能找出原因是什么 – Saggio

回答

2

FCOMPP只设置条件码FPU中的位。你可能意思是FCOMIP(如果需要,后面跟着另一个弹出),这样你可以使用条件分支指令。

此外,即使您认为您选中了SP请注意,典型的C调用约定允许修改DX,因此假设它未更改并不安全。您应该在ADD SP,DX之前重新加载元素数量。


更新:好吧,我得到它的工作(虽然我不知道,如果结果是正确的:x = 0.9516和y = 0.3072)。您应该使用JBJL因为FPU标志位C0C3 - 这是由FCOMPP根据结果集 - 将分别转移到CFZF,但JL检查SFOF这是没有意义在这里。

边注:如果您使用DWORD PTR你的代码是不是纯16位的,它只能在32个处理器上运行。

当然,你的程序可以简化很多。

+0

你长了一个点,所以我加入 FSTSW AX SAHF 但仍然无法工作 顺便说一下,编译器不熟悉FCOMIP,但我添加的只是移动标志的状态,thx!有帮助但仍不是解决方案 – shimon

+0

更新了答案。 – Jester

+0

ok我改变了它,非常感谢你! 代码现在正在工作,我不介意它纯粹的16位,这不是对这项工作的要求的一部分,割所有我剩下的就是改变它浮动和长双倍, 有什么我需要知道除了TBYTE是10而不是8以外,对于长双倍? – shimon