We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
When I use the new update C51 compiler C51 v620c to translate the following file with SRC directive, the result seems not correct,would keil surport please check it.
#pragma SRC unsigned int ui_MixedParms(unsigned char ucA,bit btCheck, unsigned int uiB){ if (btCheck) return(ucA + uiB); return(uiB - ucA); }
; TST_C_Func2.SRC generated from: TST_C_Func2.c NAME TST_C_FUNC2 ?PR?_ui_MixedParms?TST_C_FUNC2 SEGMENT CODE ?DT?_ui_MixedParms?TST_C_FUNC2 SEGMENT DATA OVERLAYABLE ?BI?_ui_MixedParms?TST_C_FUNC2 SEGMENT BIT OVERLAYABLE PUBLIC ?_ui_MixedParms?BIT PUBLIC ?_ui_MixedParms?BYTE PUBLIC _ui_MixedParms RSEG ?DT?_ui_MixedParms?TST_C_FUNC2 ?_ui_MixedParms?BYTE: uiB?042: DS 2 RSEG ?BI?_ui_MixedParms?TST_C_FUNC2 ?_ui_MixedParms?BIT: btCheck?041: DBIT 1 ; ; unsigned int ui_MixedParms(unsigned char ucA,bit btCheck, unsigned int uiB){ RSEG ?PR?_ui_MixedParms?TST_C_FUNC2 _ui_MixedParms: USING 0 ; SOURCE LINE # 2 ;---- Variable 'ucA?040' assigned to Register 'R5' ---- MOV R5,AR7 ; if (btCheck) ; SOURCE LINE # 4 JNB btCheck?041,?C0001 ; return(ucA + uiB); ; SOURCE LINE # 5 MOV A,R5 MOV R6,#00H ADD A,uiB?042+01H MOV R7,A MOV A,R6 ADDC A,uiB?042 MOV R6,A RET ?C0001: ; return(uiB - ucA); ; SOURCE LINE # 6 CLR C MOV A,uiB?042+01H SUBB A,R5 MOV R7,A MOV A,uiB?042 SUBB A,#00H MOV R6,A ; } ; SOURCE LINE # 7 ?C0002: RET ; END OF _ui_MixedParms END
?_ui_MixedParms?BYTE: uiB?042: DS 2
?_ui_MixedParms?BYTE: ucA?040: DS 1 uiB?042: DS 2
The code generated looks correct to me. Remember that the C51 compiler is pretty smart. The ucA argument is passed in R7. The uiB is passed in a fixed memory location. Since uiB is an unsigned int, it requires 2 bytes of storage. And, that's what it gets with
uiB?042: DS 2
If you assemble the so generated SRC file and the following ASM file, link them tergether, you will find the result is NOT correct!
?PR?MAIN?TST_C_CALL2 SEGMENT CODE EXTRN CODE (_ui_MixedParms) EXTRN DATA (?_ui_MixedParms?BYTE) EXTRN BIT (?_ui_MixedParms?BIT) RSEG ?PR?MAIN?TST_C_CALL2 MAIN: MOV R7, #0x34 SETB ?_ui_MixedParms?BIT MOV ?_ui_MixedParms?BYTE+01H,#00H MOV ?_ui_MixedParms?BYTE+02H,#063H LCALL _ui_MixedParms MOV A, R7 MOV B, R6 SJMP $ CSEG AT 0 STARTUP: LJMP MAIN END
looks like a documentation error, rather than a compiler bug? surely this is the way you'd want it to work - why would you want it to allocate RAM space for a parameter it's going to pass in a Register!? Note that this is not the correct route to request Keil technical support! See the 'Overview' link http://www.keil.com/forum/
OK, I've just been looking at this: C51 v6.14 does behave as described in the manual; ie it does reserve DATA space even for parameters which are passed in registers. This space is wasted, as it is never used - the parameter(s) is(are) in the register(s)!! C51 v6.20c does not behave as described in the manual; ie it does not reserve DATA space for parameters which are passed in registers. Thus it only uses DATA space for parameters which will actually use that space. So upgrading from C51 v6.14 to v6.20c could well result in a reduction in the amount of DATA space used? I don't know if this only applies when using the SRC directive, or if it's the same when compiling straight to .obj?
C51 v6.14 does behave as described in the manual; ie it does reserve DATA space even for parameters which are passed in registers. This space is wasted, as it is never used - the parameter(s) is(are) in the register(s)!! Uhhh. This is not EXACTLY true. The compiler DOES reserve the space, however, the space is not wasted. In cases where the space is allocated, once inside the function, the register contents are stored in the DATA space. This is pretty much REQUIRED when all registers are used passing arguments to the function. This effectively moves the lengthy code required to initialize the data memory from the function calls to inside the function. This saves program space while wasting a little time (in some cases). If you look at the following example:
long adder ( long a1, // Passed in registers long a2, // Passed in fixed memory long a3) // Passed in fixed memory { return (a1+a2+a3); // Returned in registers } void main (void) { long x; x = adder (1234L, 5678L, 12345687L); while (1); }
; FUNCTION _adder (BEGIN) ; SOURCE LINE # 1 0000 8F00 R MOV a1+03H,R7 0002 8E00 R MOV a1+02H,R6 0004 8D00 R MOV a1+01H,R5 0006 8C00 R MOV a1,R4 ; SOURCE LINE # 5
MODULE INFORMATION: STATIC OVERLAYABLE CODE SIZE = 31 ---- CONSTANT SIZE = ---- ---- XDATA SIZE = ---- ---- PDATA SIZE = ---- ---- DATA SIZE = ---- 16 IDATA SIZE = ---- ---- BIT SIZE = ---- ---- END OF MODULE INFORMATION.
long adder ( unsigned b1, // Passed in registers unsigned b2) // Passed in registers { return (b1+b2); // Returned in registers } void main (void) { long x; x = adder (1234, 5678); while (1); }
; FUNCTION _adder (BEGIN) ; SOURCE LINE # 1 ;---- Variable 'b2' assigned to Register 'R4/R5' ---- ;---- Variable 'b1' assigned to Register 'R6/R7' ---- ; SOURCE LINE # 4 ; SOURCE LINE # 5 0000 EF MOV A,R7 0001 2D ADD A,R5 0002 FF MOV R7,A 0003 EE MOV A,R6 0004 3C ADDC A,R4 0005 FE MOV R6,A 0006 E4 CLR A 0007 FC MOV R4,A 0008 FD MOV R5,A ; SOURCE LINE # 6 0009 ?C0001: 0009 22 RET ; FUNCTION _adder (END)
MODULE INFORMATION: STATIC OVERLAYABLE CODE SIZE = 31 ---- CONSTANT SIZE = ---- ---- XDATA SIZE = ---- ---- PDATA SIZE = ---- ---- DATA SIZE = ---- 4 IDATA SIZE = ---- ---- BIT SIZE = ---- ---- END OF MODULE INFORMATION.