When developing SS881X/SS880X series chips with keil C51, there will be the following two different sounds for the initialization of some global variables:

First, when defining this global variable, assign the variable a value at the same time, the code is as follows:

char tmp0 = 0x55;           // Not Recommended
char tmp1 = 0xAA;

void main(void)
{
    while (1);
}

Second,  after defining the global variable, assign the variable a value, the code is as follows:

char tmp0;
char tmp1;

void main(void)
{
    tmp0 = 0x55;          // GOOD
    tmp1 = 0xAA;
    while (1);
}

So what are the similarities and differences between these two methods for some global variable initialization? Obviously, tmp0 and tmp1 are eventually assigned 0x55 and 0xAA, respectively, so are they really no different? Next, let's look at the size of the code compiled by these two methods, the first compiles 152 bytes, and the second compiles 23 bytes. It is clear that the difference between the two methods is huge.

Next, we need to get to the bottom, starting with the compilation:

Let's take a look at the disassembly of Method 2 first,  because its results are more in line with our common sense.

                 C_STARTUP:
C:0x0000    020003   LJMP     C:0003
C:0x0003    787F     MOV      R0,#0x7F
C:0x0005    E4       CLR      A
C:0x0006    F6       MOV      @R0,A
C:0x0007    D8FD     DJNZ     R0,C:0006
C:0x0009    758109   MOV      SP(0x81),#tmp1(0x09)
C:0x000C    02000F   LJMP     main(C:000F)
                 main:
C:0x000F    750855   MOV      tmp0(0x08),#0x55
C:0x0012    7509AA   MOV      tmp1(0x09),#PDRV0(0xAA)
C:0x0015    80FE     SJMP     C:0015

You can see that before executing main, there are some instructions, and this code segment is named  C_STARTUP, C_STARTUP is actually the entry of the entire program execution, and the address must be 0x0000. Then there is a loop, from 0x0003->0x0007, these instructions actually do one thing, that is, clearing the 00H ~ 7FH address (128 bytes) of RAM, and use the method of indirect addressing (the first 128 bytes of RAM of SS880X/SS881X can be directly addressed or indirectly addressed), and when the 128 bytes of RAM are cleared, initialize the stack pointer register, Then jump to the main function,

In the main function, it directly assigns value to the tmp0 and tmp1 that have been assigned addresses, here is the instruction that directly assigns the constant to the address (MOV direct, #data), these two lines directly initialize the global variable.

So look at the disassembly of Method 1 to see what it did.

                 C_STARTUP:
C:0x0000    020003   LJMP     C:0003
C:0x0003    787F     MOV      R0,#0x7F
C:0x0005    E4       CLR      A
C:0x0006    F6       MOV      @R0,A
C:0x0007    D8FD     DJNZ     R0,C:0006
C:0x0009    758109   MOV      SP(0x81),#tmp1(0x09)
C:0x000C    02004A   LJMP     C_START(C:004A)
C:0x000F    020096   LJMP     main(C:0096)
C:0x0012    E4       CLR      A
C:0x0013    93       MOVC     A,@A+DPTR
C:0x0014    A3       INC      DPTR
C:0x0015    F8       MOV      R0,A
C:0x0016    E4       CLR      A
C:0x0017    93       MOVC     A,@A+DPTR
C:0x0018    A3       INC      DPTR
C:0x0019    4003     JC       C:001E
C:0x001B    F6       MOV      @R0,A
C:0x001C    8001     SJMP     C:001F
C:0x001E    F2       MOVX     @R0,A
C:0x001F    08       INC      R0
C:0x0020    DFF4     DJNZ     R7,C:0016
C:0x0022    8029     SJMP     C:004D
C:0x0024    E4       CLR      A
C:0x0025    93       MOVC     A,@A+DPTR
C:0x0026    A3       INC      DPTR
C:0x0027    F8       MOV      R0,A
C:0x0028    5407     ANL      A,#0x07
C:0x002A    240C     ADD      A,#0x0C
C:0x002C    C8       XCH      A,R0
C:0x002D    C3       CLR      C
C:0x002E    33       RLC      A
C:0x002F    C4       SWAP     A
C:0x0030    540F     ANL      A,#0x0F
C:0x0032    4420     ORL      A,#0x20
C:0x0034    C8       XCH      A,R0
C:0x0035    83       MOVC     A,@A+PC
C:0x0036    4004     JC       C:003C
C:0x0038    F4       CPL      A
C:0x0039    56       ANL      A,@R0
C:0x003A    8001     SJMP     C:003D
C:0x003C    46       ORL      A,@R0
C:0x003D    F6       MOV      @R0,A
C:0x003E    DFE4     DJNZ     R7,C:0024
C:0x0040    800B     SJMP     C:004D
C:0x0042    0102     AJMP     C:0002
C:0x0044    04       INC      A
C:0x0045    08       INC      R0
C:0x0046    102040   JBC      0x24.0,C:0089
C:0x0049    8090     SJMP     C:FFDB
C:0x004B    00       NOP     
C:0x004C    8FE4     MOV      0xE4,R7
C:0x004E    7E01     MOV      R6,#0x01
C:0x0050    93       MOVC     A,@A+DPTR
C:0x0051    60BC     JZ       C:000F
C:0x0053    A3       INC      DPTR
C:0x0054    FF       MOV      R7,A
C:0x0055    543F     ANL      A,#0x3F
C:0x0057    30E509   JNB      0xE0.5,C:0063
C:0x005A    541F     ANL      A,#0x1F
C:0x005C    FE       MOV      R6,A
C:0x005D    E4       CLR      A
C:0x005E    93       MOVC     A,@A+DPTR
C:0x005F    A3       INC      DPTR
C:0x0060    6001     JZ       C:0063
C:0x0062    0E       INC      R6
C:0x0063    CF       XCH      A,R7
C:0x0064    54C0     ANL      A,#INTCON2(0xC0)
C:0x0066    25E0     ADD      A,ACC(0xE0)
C:0x0068    60A8     JZ       C:0012
C:0x006A    40B8     JC       C:0024
C:0x006C    E4       CLR      A
C:0x006D    93       MOVC     A,@A+DPTR
C:0x006E    A3       INC      DPTR
C:0x006F    FA       MOV      R2,A
C:0x0070    E4       CLR      A
C:0x0071    93       MOVC     A,@A+DPTR
C:0x0072    A3       INC      DPTR
C:0x0073    F8       MOV      R0,A
C:0x0074    E4       CLR      A
C:0x0075    93       MOVC     A,@A+DPTR
C:0x0076    A3       INC      DPTR
C:0x0077    C8       XCH      A,R0
C:0x0078    C582     XCH      A,DPL(0x82)
C:0x007A    C8       XCH      A,R0
C:0x007B    CA       XCH      A,R2
C:0x007C    C583     XCH      A,DPH(0x83)
C:0x007E    CA       XCH      A,R2
C:0x007F    F0       MOVX     @DPTR,A
C:0x0080    A3       INC      DPTR
C:0x0081    C8       XCH      A,R0
C:0x0082    C582     XCH      A,DPL(0x82)
C:0x0084    C8       XCH      A,R0
C:0x0085    CA       XCH      A,R2
C:0x0086    C583     XCH      A,DPH(0x83)
C:0x0088    CA       XCH      A,R2
C:0x0089    DFE9     DJNZ     R7,C:0074
C:0x008B    DEE7     DJNZ     R6,C:0074
C:0x008D    80BE     SJMP     C:004D
C:0x008F    0108     AJMP     C:0008
C:0x0091    5501     ANL      A,0x01
C:0x0093    09       INC      R1
C:0x0094    AA00     MOV      R2,0x00
     4: void main(void)
C:0x0096    80FE     SJMP     main(C:0096)

Good guys, so much. The author also did not go to see what he was doing one by one, only paid attention to where RAM was initialized, and after single-step debugging, it was found that the instructions for initializing RAM were summarized in the following lines:

C:0x0016    E4       CLR      A
C:0x0017    93       MOVC     A,@A+DPTR
C:0x0018    A3       INC      DPTR
C:0x0019    4003     JC       C:001E
C:0x001B    F6       MOV      @R0,A

The focus is here (MOVC A, @A+DPTR), seeing this instruction, the author guesses: while defining a global variable, the operation of initializing the variable, for the compiler, is actually the initial value that needs to be written to RAM, read out a certain section of the code area in the form of a lookup table, and then write it to RAM. (It can be analogously referred to as read-write XDATA)

So what is the way to argue this, you can combine the compiled BIN file and disassembly, what we want to do is to write 0x55 to 08H of RAM, and  write 0xAA to 09H of RAM, so the following disassembly is actually meaningless (and will not run), his role is to make a table, and then put it in a certain address in the code area, and compile this table when running the code, so the amount of code has increased so much.

C:0x008F    0108     AJMP     C:0008
C:0x0091    5501     ANL      A,0x01
C:0x0093    09       INC      R1
C:0x0094    AA00     MOV      R2,0x00

If you have the patience to read this, you must have understood the trap of keil C51 when initializing global variables, and finally give a conclusion:

After defining a global variable, be sure to assign the initial value of the variable in the function (such as when initializing) (if the initial value is 0, it does not need to be assigned, and it will be cleared by default when the system starts), rather than when the variable is defined.

 

Original article, Please mark the attribution when reprinting.  SINHMICROwww.sinhmicro.com

标签:
SS880X SS881X keil C51 全局变量 初值

Loading Conversation