I've found lots of differences between direct compiling from C and compiling through assembler! This differences are in the dealing with functions' arguments. for example: When compiling directly from C, overlays are seems work, but in other way linker does not use any overlays, ignoring all "OVERLAYABLE" keywords in source file! Sample C program:
void fun1(int a, int b,int c,int d) { a=b=c=d; return ; } void fun2(int a, int b, int c, int d) { c=a=b=d; //fun1(a,b,c,d); return ; } main() { fun1(0,0,0,0); fun2(0,0,0,0); while (1) ; }
; .\main.SRC generated from: main.c ; COMPILER INVOKED BY: ; C:\Keil\C51\BIN\C51.EXE main.c OPTIMIZE(7,SPEED) REGFILE(.\test.ORC) NOINTPROMOTE NOPRINT SRC(.\main.SRC) NAME MAIN ?PR?_fun1?MAIN SEGMENT CODE ?DT?_fun1?MAIN SEGMENT DATA OVERLAYABLE ?PR?_fun2?MAIN SEGMENT CODE ?DT?_fun2?MAIN SEGMENT DATA OVERLAYABLE ?PR?main?MAIN SEGMENT CODE EXTRN CODE (?C_STARTUP) PUBLIC main PUBLIC ?_fun2?BYTE PUBLIC _fun2 PUBLIC ?_fun1?BYTE PUBLIC _fun1 RSEG ?DT?_fun1?MAIN ?_fun1?BYTE: a?040: DS 2 b?041: DS 2 c?042: DS 2 d?043: DS 2 RSEG ?DT?_fun2?MAIN ?_fun2?BYTE: a?144: DS 2 b?145: DS 2 c?146: DS 2 d?147: DS 2 ; void fun1(int a, int b,int c,int d) { RSEG ?PR?_fun1?MAIN _fun1: USING 0 ; SOURCE LINE # 1 ;---- Variable 'a?040' assigned to Register 'R6/R7' ---- ;---- Variable 'c?042' assigned to Register 'R2/R3' ---- ;---- Variable 'b?041' assigned to Register 'R4/R5' ---- ; a=b=c=d; ; SOURCE LINE # 2 MOV R6,d?043 MOV R7,d?043+01H MOV R2,AR6 MOV R3,AR7 MOV R4,AR6 MOV R5,AR7 ; return ; ; } ; SOURCE LINE # 4 ?C0001: RET ; END OF _fun1 ; ; void fun2(int a, int b, int c, int d) { RSEG ?PR?_fun2?MAIN _fun2: USING 0 ; SOURCE LINE # 6 ;---- Variable 'a?144' assigned to Register 'R6/R7' ---- ;---- Variable 'c?146' assigned to Register 'R2/R3' ---- ;---- Variable 'b?145' assigned to Register 'R4/R5' ---- ; c=a=b=d; ; SOURCE LINE # 7 MOV R6,d?147 MOV R7,d?147+01H MOV R4,AR6 MOV R5,AR7 MOV R2,AR4 MOV R3,AR5 ; //fun1(a,b,c,d); ; return ; ; } ; SOURCE LINE # 10 ?C0002: RET ; END OF _fun2 ; ; main() { RSEG ?PR?main?MAIN main: USING 0 ; SOURCE LINE # 12 ; fun1(0,0,0,0); ; SOURCE LINE # 13 CLR A MOV ?_fun1?BYTE+06H,A MOV ?_fun1?BYTE+07H,A MOV R3,A MOV R2,A MOV R5,A MOV R4,A MOV R7,A MOV R6,A LCALL _fun1 ; fun2(0,0,0,0); ; SOURCE LINE # 14 MOV ?_fun2?BYTE+06H,A MOV ?_fun2?BYTE+07H,A MOV R3,A MOV R2,A MOV R5,A MOV R4,A MOV R7,A MOV R6,A LCALL _fun2 ?C0003: ; while (1) ; ; SOURCE LINE # 15 SJMP ?C0003 RET ; END OF main END
LINK MAP OF MODULE: test (MAIN) TYPE BASE LENGTH RELOCATION SEGMENT NAME ----------------------------------------------------- * * * * * * * D A T A M E M O R Y * * * * * * * REG 0000H 0008H ABSOLUTE "REG BANK 0" DATA 0008H 0008H UNIT _DATA_GROUP_ IDATA 0010H 0001H UNIT ?STACK * * * * * * * C O D E M E M O R Y * * * * * * * CODE 0000H 0003H ABSOLUTE CODE 0003H 001EH UNIT ?PR?MAIN?MAIN CODE 0021H 000DH UNIT ?PR?_FUN1?MAIN CODE 002EH 000DH UNIT ?PR?_FUN2?MAIN CODE 003BH 000CH UNIT ?C_C51STARTUP OVERLAY MAP OF MODULE: test (MAIN) SEGMENT DATA_GROUP +--> CALLED SEGMENT START LENGTH ---------------------------------------------- ?C_C51STARTUP ----- ----- +--> ?PR?MAIN?MAIN ?PR?MAIN?MAIN ----- ----- +--> ?PR?_FUN1?MAIN +--> ?PR?_FUN2?MAIN ?PR?_FUN1?MAIN 0008H 0008H ?PR?_FUN2?MAIN 0008H 0008H
LINK MAP OF MODULE: test (MAIN) TYPE BASE LENGTH RELOCATION SEGMENT NAME ----------------------------------------------------- * * * * * * * D A T A M E M O R Y * * * * * * * REG 0000H 0008H ABSOLUTE "REG BANK 0" DATA 0008H 0008H UNIT ?DT?_FUN1?MAIN DATA 0010H 0008H UNIT ?DT?_FUN2?MAIN IDATA 0018H 0001H UNIT ?STACK * * * * * * * C O D E M E M O R Y * * * * * * * CODE 0000H 0003H ABSOLUTE CODE 0003H 001EH UNIT ?PR?MAIN?MAIN CODE 0021H 000DH UNIT ?PR?_FUN1?MAIN CODE 002EH 000DH UNIT ?PR?_FUN2?MAIN CODE 003BH 000CH UNIT ?C_C51STARTUP
Well, as the saying goes: don't do that, then! In the case at hand, there's no particular need at all to compile through an intermediate asm source, so don't do it, and all will be well. Longer explanation follows: Compilers can be designed so it makes no difference at all whether you go through assembler or not (typically by always going through an intermediate assembler source file) --- but Keil C51 is not designed that way. The core reason for all this is that Ax51 can't output the same amount of auxiliary information to object files as Cx51: no source debug info, and apparently no overlay steering information either. I personally consider this state of affairs a serious weakness, but since this doesn't appear likely to change any time soon, the following advice remains valid: *) Don't use SRC mode unless you absolutely have to *) If you think you have to use assembly language, do so in a separate assembly source file. *) SRC mode is useful for generating a template for such an assembly source file, but not for much more.
Hmmm, The segments are declared correctly: ?DT?_fun1?MAIN SEGMENT DATA OVERLAYABLE What version of the tools are you using? Jon
Keil 7.0.
The setup for Data Overlaying and Code Banking with A51 Assembler Modules is discussed in: http://www.keil.com/appnotes/docs/apnt_149.asp
Cite from this .pdf: "NOTES The BL51 linker/locater enables data overlaying and code banking only if at least one object module is generated by the C51 Compiler. Therefore your project should contain on C51 source file that is directly translated to an object file with the C51 compiler. In case that you do not have any C sources, you may translate an empty file with C51." Isn't it a solution of my problem? Ofcourse yes! Thanx, Oliver!