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); }
Sorry, Broeker. In last message, I missed a fragment. Here it is.
0008 L?0020: 0008 7E00 MOV R6,#00H 000A 7F08 MOV R7,#08H 000C 120000 E LCALL ?C?COPY ; FUNCTION ExStampToJDxTime (BEGIN) ; SOURCE LINE # 134 ; SOURCE LINE # 135 ; SOURCE LINE # 138 000F E500 R MOV A,oExT1+02H 0011 2409 ADD A,#09H 0013 75F00C MOV B,#0CH 0016 84 DIV AB 0017 85F000 R MOV oExT1+02H,B ; SOURCE LINE # 141 001A AF00 R MOV R7,oExT1 001C 7E00 MOV R6,#00H 001E 7C00 MOV R4,#00H 0020 7D64 MOV R5,#064H 0022 120000 E LCALL ?C?IMUL 0025 EF MOV A,R7 0026 2500 R ADD A,oExT1+01H 0028 F500 R MOV n_oJDxTime+05H,A 002A EC MOV A,R4 002B 3E ADDC A,R6 002C F500 R MOV n_oJDxTime+04H,A ...... ; SOURCE LINE # 152 017E 7B00 MOV R3,#00H 0180 7A00 R MOV R2,#HIGH n_oJDxTime 0182 7900 R MOV R1,#LOW n_oJDxTime ; SOURCE LINE # 153 0184 ?C0007: 0184 22 RET ; FUNCTION ExStampToJDxTime (END)