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.
In one of my project I am talking with MX909 Driver IC with C51 ucontroller. To initialize MX909 if I write module in Assembly language it's working fine. Once I replaced with C same module it's not working.
The only difference I can make for both assembly and C languages is NOP and _nop_() instruction. Is both instructions will take same number of machine cycles?
Thanks, Suresh Kumar Kavula
Once I replaced with C same module why on earth did you do that?
If you had taken one second to look at the generated assembly you would have found that they are identical.
My guess is that you suffer from some fallacy that e.g. a for loop is the same as a djnz loop and nothing could be farther from the truth.
If you, for some silly reason, have to "replace with C" have a look at the assembler code generated by the compiler and you will find your answer.
Erik
Erik,
Thanks for your quick response. By using keil C I am trying to generate 2.4uSeconds delay by writing 4 _nop_() instructions. For this I am using I am using AT89C5131, X1 clock Mode with 20 MHZ.
Same C routine if I replace 4 NOP instructions by using #pragma ASM working fine.
I don't know what the reason is.
ONCE MORE
LOOK AT THE ASM GENERATED BY THE COMPILER!!
Yes, disassembly generating NOP instructions only for each _nop_() instruction.
It seems problem in some where else.
Thanks a lot Erik for your help.
Yes, disassembly
That is just too cumbersome a method, why not use the .lst file?. Or to be real fancy do a 'test compile' with #pragma SRC
"Yes, disassembly generating NOP instructions only for each _nop_() instruction"
I should hope so too - that's exactly what it is defined to do: http://www.keil.com/support/man/docs/c51/c51__nop_.htm
However, this is where any code-generation guarantee ends!
It is fundamental to the nature of High-Level Languages (HLLs; including 'C') that you have absolutely no control whatsoever over the code that will be generated by the compiler.
Therefore, although the _nop_() Intrinsic Function is guaranteed to insert a single NOP instruction, you have absolutely no control whatsoever over the rest of the code that will be generated around the _nop_() "call".
Therefore, you must use an assembler routine if you need a predictable delay!
Or to be real fancy do a 'test compile' with #pragma SRC
I'd advise extra care with that approach. There's no guaranteed whatsoever that the code output in #pragma SRC mode is the same as otherwise.
The only reliable ways to find out what the compiler did are the list file, absolute list file (if linker optimizations are enabled) and disassembler/debugger views.
"There's no guaranteed whatsoever that the code output in #pragma SRC mode is the same as otherwise."
There is also no guarantee whatsoever that the results will remain the same on subsequent re-compiles!
How many times does "no guarantee whatsoever" have to be said make the point that this is a bad idea...?
www.milinkito.com/.../bart.php
Andy,
I'm going to have to make a favourite of that one!
Thanks.
----- FUNCTION main (BEGIN) ----- 8: void main(void) 9: { 10: unsigned char loop; 11: 12: for(loop=128;loop;loop--) ;---- Variable 'loop' assigned to Register 'R7' ---- 00000F 7F80 MOV R7,#080H 000011 ?C0001?TEST: 13: { 14: } 000011 DFFE DJNZ R7,?C0001?TEST 000013 ?C0004?TEST: 15: 16: while(1); 000013 80FE SJMP ?C0004?TEST ----- FUNCTION main (END) -------
Jack,
The authoritative masquerade very clearly exposed!
The compiler may implement a for loop by using a djnz.
And here's proof that a for loop is not the same as a djnz loop:
line level source 1 int main(void) 2 { 3 1 unsigned char loop; 4 1 5 1 for(loop = 0; loop != 128; loop++) 6 1 { 7 2 } 8 1 while(1); 9 1 return(0); 10 1 } C51 COMPILER V8.02 MAIN 08/15/2007 13:01:31 PAGE 2 ASSEMBLY LISTING OF GENERATED OBJECT CODE ; FUNCTION main (BEGIN) ; SOURCE LINE # 1 ; SOURCE LINE # 2 ; SOURCE LINE # 5 ;---- Variable 'loop' assigned to Register 'R7' ---- 0000 E4 CLR A 0001 FF MOV R7,A 0002 ?C0001: ; SOURCE LINE # 6 ; SOURCE LINE # 7 0002 0F INC R7 0003 BF80FC CJNE R7,#080H,?C0001 0006 ?C0004: ; SOURCE LINE # 8 0006 80FE SJMP ?C0004 ; FUNCTION main (END)
And another one:
line level source 1 int main(void) 2 { 3 1 unsigned char loop; 4 1 5 1 for(loop = 128; loop-- != 0; ) 6 1 { 7 2 } 8 1 while(1); 9 1 return(0); 10 1 } C51 COMPILER V8.02 MAIN 08/15/2007 13:03:32 PAGE 2 ASSEMBLY LISTING OF GENERATED OBJECT CODE ; FUNCTION main (BEGIN) ; SOURCE LINE # 1 ; SOURCE LINE # 2 ; SOURCE LINE # 5 ;---- Variable 'loop' assigned to Register 'R7' ---- 0000 7F80 MOV R7,#080H 0002 ?C0001: 0002 AE07 MOV R6,AR7 0004 1F DEC R7 0005 EE MOV A,R6 0006 70FA JNZ ?C0001 ; SOURCE LINE # 6 ; SOURCE LINE # 7 0008 ?C0003: ; SOURCE LINE # 8 0008 80FE SJMP ?C0003 ; FUNCTION main (END)
If you know the compiler and the right syntax, it is possible to get a djnz when using a for loop. There is no guarantee.
"The authoritative masquerade very clearly exposed!"
Not really.
All it has shown is that, in one particular case, the for loop just happened to turn out as a simple DJNZ loop.
In general, you can't assume that.
eg, in the example shown, the oprimiser has happened to assign the loop counter to R7 - unrelated changes in the source code could change that, which may or may not affect the loop timing!
One more time: There is absolutely no guarantee whatsoever etc, etc,...
Does "Jack" now need an audience to give some applause whenever he (doesn't) find an error in Erik's arguments ?
int main(void) { unsigned char loop; for(loop = 128; loop != 0; loop--) { } while(1); return(0); }
Here's an easy question:
Assume nothing about the compiler, except that it is actually working correctly. The for loop above will result in (more than one answer may be correct):
a) a DJNZ loop b) another type of loop c) no loop at all