Hi all,
In my project, I write some codes like this sample:
1 void foo(char xdata *pbuf, char a, char b) 2 { 3 int pdata bufaddr; 4 long pdata testval; 5 6 testval = 0x200; 7 bufaddr = pbuf; 8 } 9 10 void main(void) 11 { 12 char xdata buf[10]; 14 15 foo(buf, 0, 1); 16 }
And C51 would be compile these codes to this assembly:
; FUNCTION _foo (BEGIN) ; SOURCE LINE # 1 0000 8D00 R MOV a,R5 0002 8B00 R MOV b,R3 ;---- Variable 'pbuf' assigned to Register 'DPTR' ---- 0004 8F82 MOV DPL,R7 0006 8E83 MOV DPH,R6 ; SOURCE LINE # 2 ; SOURCE LINE # 6 0008 7800 R MOV R0,#LOW testval 000A 120000 E LCALL ?C?LSTKPDATA 000D 00 DB 00H 000E 00 DB 00H 000F 02 DB 02H 0010 00 DB 00H ; SOURCE LINE # 7 0011 AF82 MOV R7,DPL 0013 7800 R MOV R0,#LOW bufaddr 0015 E583 MOV A,DPH 0017 F2 MOVX @R0,A 0018 08 INC R0 0019 EF MOV A,R7 001A F2 MOVX @R0,A ; SOURCE LINE # 8 001B 22 RET ; FUNCTION _foo (END) ; FUNCTION main (BEGIN) ; SOURCE LINE # 10 ; SOURCE LINE # 11 ; SOURCE LINE # 14 0000 7E00 R MOV R6,#HIGH buf 0002 7F00 R MOV R7,#LOW buf 0004 7B01 MOV R3,#01H 0006 E4 CLR A 0007 FD MOV R5,A 0008 020000 R LJMP _foo ; FUNCTION main (END)
C51 would assign parameter pbuf to DPTR when function foo is called. Then in foo function, program first would call ?C?LSTKPDATA to assign a constant long type value to testval. ?C?LSTKPDATA would do the following assembly:
D083 POP DPH(0x83) D082 POP DPL(0x82) E4 CLR A 93 MOVC A,@A+DPTR F2 MOVX @R0,A 08 INC R0 7401 MOV A,#0x01 93 MOVC A,@A+DPTR F2 MOVX @R0,A 08 INC R0 7402 MOV A,#0x02 93 MOVC A,@A+DPTR F2 MOVX @R0,A 08 INC R0 7403 MOV A,#0x03 93 MOVC A,@A+DPTR F2 MOVX @R0,A 7404 MOV A,#0x04 73 JMP @A+DPTR
When finished ?C?LSTKPDATA, program would assign pbuf value to bufaddr. But pbuf is stored in DPTR, and ?C?LSTKPDATA used DPTR to assgin value before, it cause pbuf value in DPTR is overwrited, so the bufaddr would store the wrong value.
It seems this situation is caused by optimization of C51. I want to ask whether any method to prevent this situation occur.
Thanks all.
Sorry, it seems that my sample code let all misunderstand my question.
That's one of the common problems caused by trying to present a problem while not presenting the actual problem. Writing good problem reports is a seriously underestimated skill.
It can take very deep understanding of all tools and languages involved to boil down a given source code to the minimal, yet sufficient example that still actually demonstrates the problem faithfully. You got one thing right in your first code sample: self-sufficiency, i.e. you showed code that actually compiled as-is, with no further assumptions, unknown include files, etc (Unfortunately, you got this wrong the second time round). You did get the other major aspect wrong the first time round, though: making sure that the code is still functionally equivalent to the original which you didn't want to publish. Exchanging static, volatile fixed-address variables for unqualified automatic ones totally changed the scope of the problem.
It would still be better if you changed the type of CardFifoAdrReg to (xdata void *), and brought your second sample code into stand-alone, compilable form, but from what I can see, that does look like you might have a support case to bring to Keil's attention there. Because whatever goes wrong there, it appears to happen between the compiler and its support library functions, so there's little else you could do about it.
A possible workaround suggests itself, though: switch order of assignments to those two registers, if the hardware behind them permits it.