2013-01-18 75 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