2013-01-18 3 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); 
} 

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

코드에서 오류를 발견하도록 다른 사람에게 질문하는 것은 생산성이 떨어집니다. 디버거에서 코드를 단계별로 실행해야합니다. 그러면 당신은 그것이 정확히 "붙어있는"곳을 발견 할 것입니다. –

+0

날 믿어, 내가 마지막 3 일 동안 디버거에 살았어, 아직도 찾을 수 없습니다. ( 내가 볼 수 있듯이 나는 SP를 확인했다. 디버거에서보아야한다는 것을 의미한다. – shimon

+3

글쎄, 그것은 확실히 붙어 있지 않다. 이유가 무엇인지 알아 내기 위해 디버그해야합니다. – Saggio

답변

2

FCOMPP은 조건 코드를 설정 FPU의 비트. 조건부 분기 명령어를 사용할 수 있도록 FCOMIP을 (아마도 필요한 경우 다른 팝업이 뒤따라야 함) 의미했을 것입니다.

또한 SP을 확인했다고 말하면 일반적인 C 호출 규칙을 사용하면 DX을 수정할 수 있으므로 변경되지 않았다고 가정해도 안전하지 않습니다. ADD SP,DX 앞에 요소 수를 다시로드해야합니다.


업데이트는 (: X = 0.9516와 y = 0.3072 결과가 맞다면 나도 몰라 있지만) 좋아, 나는 일을 입수했습니다. 여기에서 의미가 아닌 각각 CFZF로 전송되지만 JL 검사 SFOF - 결과에 따라 FCOMPP 의해 설정된 - 넌 JB하지 FPU 플래그 비트 C0C3 때문에 JL를 사용한다.

사이드 노트 : DWORD PTR을 사용하면 코드가 순수한 16 비트가 아니며 32 비트 프로세서에서만 실행됩니다.

물론 프로그램이 많이 단순화 될 수 있습니다.

+0

을 계속 중지 shpuld해야하는 경우에도 때 중지 해달라고입니다 그런데 컴파일러는 FCOMIP에 익숙하지 않지만, 플래그의 상태를 옮긴다는 것이 추가되었습니다. 도움이되었지만 여전히 해결책이 아닙니다. – shimon

+0

답변을 업데이트했습니다. – Jester

+0

괜찮아. ive 그것을 바꿨어, 정말 고마워! 코드가 작동 중입니다. 순수한 16 비트를 마음에 두지 않습니다.이 작업에 대한 요구 사항 중 일부가 아닙니다. 나머지는 모두 float과 long double로 변경하는 것입니다. 알아 두어야 할 것이 있습니다. TBYTE를 제외하고 long double에 관한 것은 8 대신에 10입니까? – shimon