C51 will generate different code for the following function:
void timer1 (void) interrupt 3 { second; #pragma asm clr TF1 #pragma endasm }
Compiler v8.08 code (edited)
USING 0 timer1: ; #pragma asm clr TF1 ; #pragma endasm RETI
Compiler v8.17 code (edited)
USING 0 timer1: PUSH ACC PUSH B PUSH DPH PUSH DPL PUSH PSW MOV PSW,#00H PUSH AR0 ... PUSH AR7 USING 0 ; #pragma asm clr TF1 ; #pragma endasm POP AR7 ... POP AR0 POP PSW POP DPL POP DPH POP B POP ACC RETI
C51 v8.17 generates code to save and restore all registers, as soon as the (very simplified, nonsense) C function contains any assembly source, whereas C51 v8.08 does not. For a function containing equivalent C code only (TF=0), nothing would be saved with either version.
Is there a reason for the different code generated by v8.17 ? How could saving/restoring of the registes be avoided ?
#pragma asm clr TF1 #pragma endasm
is equivalent to TF1 = 0;
The asm 'confuses' the compiler. With '51 compilers NEVER use pragma asm, if you HAVE to go asm use an asm module.
Erik
And what v8.17 does is correct. The compiler has no way of knowing what exactly the assembly code contained within the function will do, so it has to assume that all registers are modified.
(By pure coincidence, I'm facing a similar problem with a compiler from a different manufacturer. There, the compiler "optimizes out" function arguments if a C function consists of inline assembly - apparently it never "sees" them used by C code and therefore thinks they're never used. Needless to say, the results are quite fatal.)
Is there a reason for the different code generated by v8.17 ?
Yes. v8.16 does the correct thing.
How could saving/restoring of the registes be avoided ?
Write the whole ISR in assembly (as in "separate assembly source file), or write it purely in C.
(should be: v8.17).
Thanks for the comments.
Of course I'm aware, that the code used in the example could have beeen written in C without problems. It's just a very simple example - the real source file contains some 100 lines of assembly code used in an optimized interrupt function.
For C functions the compiler does the right thing and preserves only those registers that are used. As soon as there is an assembly section, all registers get saved and restored by v8.17. In my opinion it would be better to save only the registers modified by C code (generated translated by the compiler). If someone uses assembly sections, he should preserve the registers modified by that section himself.
Also I'm still not happy if the compiler's behaviour changes without notice after quite a long time. But maybe I just overlooked something.
Anyway - I agree that the best way would be to put assembly code where it belongs - in an asm module.
Also I'm still not happy if the compiler's behaviour changes without notice after quite a long time.
Well, IMHO you were practically begging for that kick in the head. Whether you should be thankful that Keil waited so long to deliver it, or pissed off that they didn't do so immediately, is kinda besides the point.
It's been discussed to death in here that Keil C51's inline assembly is hardly ever the right thing to use. Split up the work clearly between what you want to do (written in assembly source files), and what you want C51 to do for you (written in C). Don't throw sticks called "#pragma asm" among its gears if you want C51 to work well.
"Well, IMHO you were practically begging for that kick in the head."
Agreed. By virtue of the fact that you are not one of the approved regulars it seems you invite ridicule ;)
Seriously though, I do not know anyone who actually uses the inline assembler with C51 nor would I ever recommend its use. It just begs the question, why did Keil ever include such a facility, just to be disparaged by the professionals?
It just begs the question, why did Keil ever include such a facility, just to be disparaged by the professionals?
because of insistence from so called professionals.
There are, in Keil, many things, the use of which, is extremely deterimental to code running under this architecture and the only reason to include them must be demand from so called professionals that refuse to "work with the architecture". A true professional would make him/herself totally familiar with (the limitations created by) the architecture before touching the keyboard.
I could make a list of such features, but do not want to start a mile long thread about very unique cases where it might be justified to work against the architecture; such decisions should, of course, only be made by a true professional totally familiar with the architecture.
because of insistence from so called professionals
Really? How do you know that?
In much the same way a true professional would make himself totally familiar with the programming language before touching the keyboard, no?
I could make a list of such features, but do not want to start a mile long thread about very unique cases where it might be justified to work against the architecture;
Oh, but please do.
such decisions should, of course, only be made by a true professional totally familiar with the architecture.
I won't bother to reiterate.
Hi Jack,
Nice to see you back :)
OK, I have decided: I'm going to study C51 architecture so I can figure out myself who the villain here actually is :-). You see, I'm a sinner living in the 32 bit world (but you can do so many wonderful things in my realm- LCD control + networking + USB + room to spare, try the wonderful machine called LPC2478, and no, I don't work for NXP...). I guess only then I will understand what "wrestling something in the architecture" really means!
OK, I have decided: I'm going to study C51 architecture so I can figure out myself who the villain here actually is :-).
Well, let me put it like this: Keil's implementation of inline assembly (last I looked) is sufficiently half-baked to suggest that they didn't really bother to design it carefully. To mention just one major show-stopper: a single inline assembly fragment in a source file kills debug information for that entire module. And it disables a considerable subset of available optimizations --- again, for the entire module. Judging by what throwing one into the compiler's works causes, it should not be called "#pragma asm" but rather "#pragma monkey_wrench".
Which begs the question: if they didn't plan on doing it properly, why do it at all? There had to be some reason to spend money on the existing implementation, and among the more plausible ones that come to mind is that some customers out there (or their beancounting departments) may be shopping for tools strictly by bullet point list, without a care in the world whether those features can actually be used productively. I.e. maybe Keil thought they could not afford not having that "inline assembly support: [X]" point checked on their fact sheet.
Hans-Bernhard,
This is a most shocking revelation. I never thought an entire module would be affected by this.
there is no villain but the user (or chooser) if the user do not know the implications of using a 'feature' (s)he is at fault for using it if the chooser (of microcontroller type) does not make sure that the required features are available in the choice (s)he is at fault for choosing it
NOW, ever so often, the fault is at the user because the required functiobality could easily be implemented in the choice withou any deterimental effects, just not by the "first thought" but by a different technique beneficial to the architecture/compiler.
NOW, of course there is the "I am important, the product is not" group (e.g. "Jack Sprat") that will insist "if it is defined in C I do not care if the processor is inefficient doing it".
there is no villain but the user (or chooser)
<another episode of 'Completely Missing The Point' snipped>
Another day aboard the starship 'Confusing Exercise':
Crank the debugger up to warp 9, Scotty, we're about to start coding.
Och, but Captain, she cannae tak it! Can we nae use the Standard instead?
Afraid not, Scotty, we've always flown by the seat of our pants in this ship and we're not about to change now.
<sighs> Aye aye, Captain.
* 5A3266E3-82B2-4DCB-8A0C-23BE1236021C throws a handful of sawdust on the combatants in hope thatthey will quickly forget the imminent fight and instead start cleaning their pelts.