hi, I'm a C51 beginner,I writen a C51 program which generated binary code about 30Kbytes, but in .asm program,it generated binary code only about 16Kbyte. How can I save the C51 program's code size? thanks!
Jon is correct, you have to look at the map file from the linker. This is a file with an .M51 extension. One thing that the C51 compiler doesn't optimize well is indexed array access. Since there are no index registers as there are in X86 devices, every time an indexed array is accessed, the address is calculated. Using pointer access will reduce the code and also improve speed by a significant amount. You should also look carefully at the memory model you use, and memory access, as this can also drastically affect code size and speed.
"every time an indexed array is accessed, the address is calculated. Using pointer access will reduce the code and also improve speed by a significant amount." This is not necessarily true! I looked at this in some detail a while ago, and found that adding a pointer may actually use more code and, therefore, be slower! eg,
for (i = n; i != 0; i--) { *bcdP += '0'; ++bcdP; }
for (i = n; i != 0; i--) { bcdP[i] += '0'; }
I had the unusual experience of taking an application written in assembler and re-coding it in 'C' to the same design. The original assembler was carefully written and needed just over 16K bytes. The 'C' code required some careful work on it to bring the size down, but ended up at just over 24K bytes. I think that must put Keil C in a favourable light – not many compilers would achieve such a small increase in program size. Still, work was required. As Tom points out, memory models are key to getting program size down. I suggest that you should compile with a large default memory model, but specify a memory model for each function (small, compact or large) depending upon how fast and how often it must run. Global variables may also be placed in a specific area of memory. Once your application is building, you can use the source browser to find out which variables are most frequently accessed by your application. To minimise program size (and usual increase speed) these variables should be placed in memory in the following order of preference: data, pdata, xdata. The exception is arrays – these are often too big to justify putting data and are usually best placed in pdata or xdata. Small arrays might be placed in idata. It is well worth getting to know the Source browser - its a very useful tool. In most cases, pre and post decrements should be removed from within statements and placed in separate statements. Generally, the compiled code is small and quicker. The only exceptions to this rule-of-thumb are the following constructs:
unsigned char loop; ... loop = 100; do { // stuff } while ( --loop != 0 );
unsigned char count; ... if (--count != 0 ) { // stuff }
Andrew was correct. I should have said multiple dimension arrays in my previous posts. This access makes the code recalculate the address in loops, rather than just incrementing a pointer. This usually requires one or more multiplies in the code which usually takes awhile. He makes an excellent point that you really need to look at the assembler code that results when you are trying to optimize execution speed or size.