This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

C51 Compiler Bug, Help Please !

I catch a C51 compiler bug when debugging some functions to calculate time differrence.
The main function's prints out shows that function DifferExStamp(T1,T2) give error time differrence, but DifferJDxTime(djT1,djT2) give correct results.
When I check into disassembly code in uvision IDE, i can see that the "data overlaying" for function DifferExStamp(...) -> DifferJDxTime(...) is incorrect, leading the argument djT1 (a return value) be destroyed by the function call to calculate djT2.

The C51 compiler version is 7.08, code optimization level is 8.

The codes are attached below.

Is the Compiler wrong, or my wrong ?
Please Help me. Thanks.

//==========================================================

#include <reg52.h>		// special function register 8052
#endif
#include <stdio.h>
#include <stdlib.h>  /* For randomize function */

typedef unsigned char BYTE;
typedef unsigned int WORD;
typedef unsigned long ULONG;
typedef bit BOOL;

typedef struct tagExDate
{
	BYTE cCent;
	BYTE cYear;
	BYTE cMon;
	BYTE cDay;
} CExDate;

typedef struct tagExTime
{
	BYTE cHour;
	BYTE cMin;
	BYTE cSec;
	BYTE cX100ms;
} CExTime;

typedef struct tagExStamp
{
	CExDate Date;
	CExTime	Time;
} CExStamp;

typedef struct tagJDxTime
{
	long lDays;
	ULONG dwX100ms;
} CJDxTime;

CJDxTime ExStampToJDxTime(CExStamp oExT1);
CExStamp JDxTimeToExStamp(CJDxTime oJDxT1);

CJDxTime DifferExStamp(CExStamp oExT1, CExStamp oExT2);
CJDxTime DifferJDxTime(CJDxTime oJDxT1, CJDxTime oJDxT2);

BOOL IsBadExStamp(CExStamp oExT);

void ExStampToString(CExStamp oExTime, char *szTime);

#define SECONDS_PER_MINUTE (60)
#define SECONDS_PER_HOUR (60*60)
#define SECONDS_PER_DAY (24*60*60L)

#define BAUD9600_TH1	0xFA    /*9600 BAUD in 22.1184MHz.T1@Mode2,bit SMOD=0.*/
#define BAUD_TH1 BAUD9600_TH1

void main(void)
{
	CExStamp xdata n_oExT1, xdata n_oExT2, xdata n_oNewExT;
	CJDxTime xdata n_oJDxT1, xdata n_oJDxT2, xdata n_oNewJDxT, xdata n_oJDxDletaT;
	BYTE xdata n_szBuf[32];
	char cResult;

	TMOD = (TMOD & 0x0F) | 0x20;

	TH1=BAUD_TH1;			/*Setup initial baudrate.*/
	TL1=BAUD_TH1;

	SCON = 0x52;			/*(0x52) initialize UART to mode 1   */

	TR1 = 1;				//	Open T1 as baudrate generator

	printf("Please Input 1 Date (as 1902-03-22):");
	scanf("%2bd%2bd-%2bd-%2bd",&n_oExT1.Date.cCent,&n_oExT1.Date.cYear, &n_oExT1.Date.cMon,&n_oExT1.Date.cDay);
	printf("\nPlease Input 1 Time (as 20:02:23.4):");
	scanf("%2bd:%2bd:%2bd.%1bd",&n_oExT1.Time.cHour,&n_oExT1.Time.cMin,&n_oExT1.Time.cSec,&n_oExT1.Time.cX100ms);

	if (IsBadExStamp(n_oExT1))
	{
		printf("\nYou Input a BAD DateTime !\n");
		return;
	}
	else
	{
		ExStampToString(n_oExT1,n_szBuf);
		printf("\nYou Input a GOOD DateTime:%s,",n_szBuf);

		n_oJDxT1 = ExStampToJDxTime(n_oExT1);
		printf("\nThe DaysTime is:%ld-%lu. ",n_oJDxT1.lDays,n_oJDxT1.dwX100ms);
	}

	printf("Please Input 2 Date (as 1902-03-22):");
	scanf("%2bd%2bd-%2bd-%2bd",&n_oExT2.Date.cCent,&n_oExT2.Date.cYear,	&n_oExT2.Date.cMon,&n_oExT2.Date.cDay);
	printf("\nPlease Input 2 Time (as 20:02:23.5):");
	scanf("%2bd:%2bd:%2bd.%1bd",&n_oExT2.Time.cHour,&n_oExT2.Time.cMin,&n_oExT2.Time.cSec,&n_oExT2.Time.cX100ms);

	if (IsBadExStamp(n_oExT2))
	{
		printf("\nYou Input a BAD DateTime !\n");
		return;
	}
	else
	{
		ExStampToString(n_oExT2,n_szBuf);
		printf("\nYou Input a GOOD DateTime:%s, ",n_szBuf);

		n_oJDxT2 = ExStampToJDxTime(n_oExT2);
		printf("\nThe DaysTime is:%ld-%lu. ",n_oJDxT2.lDays,n_oJDxT2.dwX100ms);
	}

	//====return error "difference time" !!!=============
	n_oJDxDletaT = DifferExStamp(n_oExT1, n_oExT2);
	printf("\nThe Difference DateTime (T1-T2) is:%ld-%lu.\n",n_oJDxDletaT.lDays,n_oJDxDletaT.dwX100ms);
	//
	//====return correct "difference time" !!!=============
	n_oJDxDletaT = DifferJDxTime(n_oJDxT1, n_oJDxT2);
	printf("The Difference DaysTime (T1-T2) is:%ld-%lu.\n",n_oJDxDletaT.lDays,n_oJDxDletaT.dwX100ms);
}

CJDxTime ExStampToJDxTime(CExStamp oExT1)
{
	CJDxTime n_oJDxTime;

	oExT1.Date.cMon = (oExT1.Date.cMon + 9)%12;

#define wYear *((WORD*)&(n_oJDxTime.dwX100ms))
	wYear = (WORD)oExT1.Date.cCent*100 + oExT1.Date.cYear;
	if (oExT1.Date.cMon/10)
	{
		wYear -= 1;
	}

	n_oJDxTime.lDays = (ULONG)wYear*365L + wYear/4 - wYear/100 + wYear/400 + (oExT1.Date.cMon*306 + 5)/10 + (oExT1.Date.cDay - 1);
#undef wYear

	n_oJDxTime.dwX100ms = (ULONG)oExT1.Time.cHour*((ULONG)SECONDS_PER_HOUR*10)

+(WORD)oExT1.Time.cMin*((WORD)SECONDS_PER_MINUTE*10) +(WORD)oExT1.Time.cSec*10 +oExT1.Time.cX100ms;

	return n_oJDxTime;
}

CJDxTime DifferExStamp(CExStamp oExT1, CExStamp oExT2)
{
	//===Data overlay improperly !!!
	return DifferJDxTime((ExStampToJDxTime(oExT1)),(ExStampToJDxTime(oExT2)));
}

CJDxTime DifferJDxTime(CJDxTime oJDxT1, CJDxTime oJDxT2)
{
	if (oJDxT1.dwX100ms < oJDxT2.dwX100ms)
	{
		oJDxT1.lDays --;
		oJDxT1.dwX100ms += (ULONG)SECONDS_PER_DAY*10L;
	}

	oJDxT1.dwX100ms -= oJDxT2.dwX100ms ;
	oJDxT1.lDays -= oJDxT2.lDays ;

	return oJDxT1;
}

BOOL IsBadExStamp(CExStamp oExT)
{
	if ((oExT.Time.cSec > 59) || (oExT.Time.cMin > 59) || (oExT.Time.cHour > 23)
		|| (oExT.Date.cCent < 19) || (oExT.Date.cCent > 99) || (oExT.Date.cYear > 99)
		|| (oExT.Date.cMon == 0) || (oExT.Date.cMon > 12)
		|| (oExT.Date.cDay == 0) || (oExT.Date.cDay > 31))
		return 1;

	return 0;
}

void ExStampToString(CExStamp oExTime, char *szTime)
{
	sprintf(szTime,"%02bd%02bd-%02bd-%02bd %02bd:%02bd:%02bd.%1bd",oExTime.Date.cCent,oExTime.Date.cYear,
		oExTime.Date.cMon,oExTime.Date.cDay,oExTime.Time.cHour,oExTime.Time.cMin,oExTime.Time.cSec,oExTime.Time.cX100ms);
}