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

may be a BUG in Keil c51 ? (32bit calculations)

Look at this program:

/*------------------------------------------------------------------------------*/
#include <reg51.h>
#include <stdio.h>


typedef unsigned long uint32;
typedef unsigned short uint16;
typedef unsigned char uint8;

#define MEMORY xdata

#define StructMEMORY xdata

typedef struct {
  uint16 lArg0;
  uint32 lArg1;
} MyStruct;

uint8 xdata * MEMORY lPtr;

MyStruct StructMEMORY m;

void MyInit() {

 m.lArg0=8;
 m.lArg1=2;

 lPtr=(uint8 xdata *)0xddd3;
}

void bug_0(MyStruct StructMEMORY *p) {
static uint32 MEMORY lResults[4];

 lResults[0]=((uint32)lPtr) + p->lArg1 + (uint32)(p->lArg0);
 lResults[1]=p->lArg1 + (uint32)(p->lArg0) + ((uint32)lPtr);


 lResults[2]=((uint32)lPtr);
 lResults[2]+=p->lArg1 + (uint32)(p->lArg0);

 lResults[3]=(uint32)(lPtr+p->lArg1 + (uint32)(p->lArg0));

 if (lResults[0]==lResults[1] && lResults[1]==lResults[2] && lResults[2]==lResults[3])
    printf("\nNo problems.");
  else
    for(;/* BUG */;);

}

void main() {

 MyInit();
 bug_0(&m);
}
/*------------------------------------------------------------------------------*/

Try to compile it and run it. You will get the endless loop.

i used a 7.01 ver. of c51

Project sets:
Target i8051AH
[v]Use on-chip rom
off-chip xdata memory: 0x0000-0x01ff
memory model: small, code rom size: small

Michael S.

Parents
  • Hello.

    // something wrong, when casting m.lArg0.
     lResults[0]=((uint32)lPtr) + ((uint32)(m.lArg0)); result = 1BBA6
     // ok; result = DDDB
     lResults[1]=((uint32)lPtr);
     lResults[1] += ((uint32)(m.lArg0));
    

    I also had it in view of when has placed the first initial text on C in heading of a theme. The others lResults have been added to show,
    In - the first:
    lResults[0]=((uint32)lPtr) + p->lArg1 + (uint32)(p->lArg0);
    lResults[1]=p->lArg1 + (uint32)(p->lArg0) + ((uint32)lPtr);
    
    From change of places composed the result has changed!!!! This fact can be seen at step-by-step performance in a simulator. lResults [0] and lResults [1] are not equal.

    In - the second:

    At a partition of compound addition on parts, the compiler has generated the machine code calculating correct result:
    lResults[2]=((uint32)lPtr);
    lResults[2]+=p->lArg1 + (uint32)(p->lArg0);
    

    In – the third:
    Addition the pointer and integer (such operation is allowable in language C and for c51 too it is allowable) and then reduction of the received pointer works and, strangely enough, too gives correct result. Here it is possible to tell: to result the pointer in the integer type it is impossible, what it is absurdity but then the compiler should make at least the warning at compilation, however Keil c51 it has not made (I can has not included what or options or #pragma ?):
    lResults[3]=(uint32)(lPtr+p->lArg1 + (uint32)(p->lArg0));
    

    And the most important, I have found out this mistake, debugging the project for the device on at89c55, there there was such sequence of a code:
    …….
    uint8 XDATA * DATA RAMDISK;
    …….
    
    /* write to file */
    void rdisk_fwrite(file_entry XDATA *mfile, uint8 XDATA *buff, uint16 len) {
    uint16 DATA i;
    
    #ifdef __SELECT_ADAPTER_CONFIG
    
    uint8 XDATA * DATA ptr;
    
     ptr=&RAMDISK[mfile->file_start_ram_index+mfile->file_len];
     i=len;
     while (i--)
    	 *ptr++ = *buff++;
    #else
    # ifdef __SELECT_TERMINAL_CONFIG
    
    MEMORY_UINT DATA ptr;
    uint8 DATA lByte;
    
    /* >>>>>>>>>>>>>>>>>>>>>here the simulator reported strange result in 'ptr' variable */
     ptr=((MEMORY_UINT)RAMDISK)+mfile->file_start_ram_index+(MEMORY_UINT)mfile->file_len;
    /* >>>>>>>>>>>>>>>>>>>>>here the simulator reported strange result in 'ptr' variable */
    
     i=len;
     while (i--) {
    	   lByte=*buff++;
    	   RAMDISK_put(ptr, lByte);
    	   ptr++;
     }
    
    # endif
    #endif
    
     buff-=len;
     update_crc(buff, len, &mfile->file_csum);
     mfile->file_len+=len;
    }
    
    In the specified place the simulator showed 'wild' result. When I have spread out addition on components, I have received that is necessary on sense of the program.

    And already at house I have outlined the small project on Keil C and have seen the same mistakes, have then decided to experiment with the order of calculation of expression and as a result the initial source code which I have placed in heading of a theme has turned out.


    I want to thank to all participating in discussion, probably it is fast and with the answer on this problem support@keil.com will come and will be solved, where also what particularly the mistake is in c51, what to deny already there is no sense as it seems to me.

Reply
  • Hello.

    // something wrong, when casting m.lArg0.
     lResults[0]=((uint32)lPtr) + ((uint32)(m.lArg0)); result = 1BBA6
     // ok; result = DDDB
     lResults[1]=((uint32)lPtr);
     lResults[1] += ((uint32)(m.lArg0));
    

    I also had it in view of when has placed the first initial text on C in heading of a theme. The others lResults have been added to show,
    In - the first:
    lResults[0]=((uint32)lPtr) + p->lArg1 + (uint32)(p->lArg0);
    lResults[1]=p->lArg1 + (uint32)(p->lArg0) + ((uint32)lPtr);
    
    From change of places composed the result has changed!!!! This fact can be seen at step-by-step performance in a simulator. lResults [0] and lResults [1] are not equal.

    In - the second:

    At a partition of compound addition on parts, the compiler has generated the machine code calculating correct result:
    lResults[2]=((uint32)lPtr);
    lResults[2]+=p->lArg1 + (uint32)(p->lArg0);
    

    In – the third:
    Addition the pointer and integer (such operation is allowable in language C and for c51 too it is allowable) and then reduction of the received pointer works and, strangely enough, too gives correct result. Here it is possible to tell: to result the pointer in the integer type it is impossible, what it is absurdity but then the compiler should make at least the warning at compilation, however Keil c51 it has not made (I can has not included what or options or #pragma ?):
    lResults[3]=(uint32)(lPtr+p->lArg1 + (uint32)(p->lArg0));
    

    And the most important, I have found out this mistake, debugging the project for the device on at89c55, there there was such sequence of a code:
    …….
    uint8 XDATA * DATA RAMDISK;
    …….
    
    /* write to file */
    void rdisk_fwrite(file_entry XDATA *mfile, uint8 XDATA *buff, uint16 len) {
    uint16 DATA i;
    
    #ifdef __SELECT_ADAPTER_CONFIG
    
    uint8 XDATA * DATA ptr;
    
     ptr=&RAMDISK[mfile->file_start_ram_index+mfile->file_len];
     i=len;
     while (i--)
    	 *ptr++ = *buff++;
    #else
    # ifdef __SELECT_TERMINAL_CONFIG
    
    MEMORY_UINT DATA ptr;
    uint8 DATA lByte;
    
    /* >>>>>>>>>>>>>>>>>>>>>here the simulator reported strange result in 'ptr' variable */
     ptr=((MEMORY_UINT)RAMDISK)+mfile->file_start_ram_index+(MEMORY_UINT)mfile->file_len;
    /* >>>>>>>>>>>>>>>>>>>>>here the simulator reported strange result in 'ptr' variable */
    
     i=len;
     while (i--) {
    	   lByte=*buff++;
    	   RAMDISK_put(ptr, lByte);
    	   ptr++;
     }
    
    # endif
    #endif
    
     buff-=len;
     update_crc(buff, len, &mfile->file_csum);
     mfile->file_len+=len;
    }
    
    In the specified place the simulator showed 'wild' result. When I have spread out addition on components, I have received that is necessary on sense of the program.

    And already at house I have outlined the small project on Keil C and have seen the same mistakes, have then decided to experiment with the order of calculation of expression and as a result the initial source code which I have placed in heading of a theme has turned out.


    I want to thank to all participating in discussion, probably it is fast and with the answer on this problem support@keil.com will come and will be solved, where also what particularly the mistake is in c51, what to deny already there is no sense as it seems to me.

Children