I have a problem. I write a function in another c source file not main file, in this function nothing do, and I declare the function as extern. In main function I invoke it 200 times. However, the compiler does not use registerbank as counter. Why?
extern void func1(void); void func2(void) { unsigned char data i; for(i=200;i;i--); } main() { unsigned char data i,j; for(i=200;i;i--) // store i in 0x08 { func1(); } for(j=200;j;j--) // store j in R6 { func2(); } } the assembly code: C:0x0003 7508C8 MOV 0x08,#TMR2CN(0xC8) 19: { 20: func1(); C:0x0006 120025 LCALL func1(C:0025) 21: } C:0x0009 D508FA DJNZ 0x08,C:0006 22: for(j=200;j;j--) C:0x000C 7EC8 MOV R6,#TMR2CN(0xC8) 23: { 24: func2(); C:0x000E 120020 LCALL func2(C:0020) 25: } C:0x0011 DEFB DJNZ R6,C:000E
Why do you have separate variables - 'i' and 'j' - to index the two loops?
If it really matters to you how the code is implemented at the register level, then you need to be using assembler!
"However, the compiler does not use registerbank as counter."
I assume you're asking why (for example) R7 isn't being used as your counter?
Probably something to do with the fact that you've explicitly told the compiler to store the variables in data space.
But that is true of both of them - so why did the compiler just put one of them in a Register...?
Or is it?
Maybe
unsigned char data i,j;
Is equivalent to
unsigned char data i; unsigned char j;
Sorry, I missed that bit.
Anyway, yes, I think you are correct ...
unsigned char *i, j;
is equivalent to:
unsigned char *i; unsigned char j;
Is it not???
I never use the first one, precisely because someone quiclky scanning the code might make a bad assumption.
Keil has somehow forgotten to specify if "data" binds to the left or to the right, but their own placement of the keyword does give an indication that it binds to the variable and not to the type, i.e. that it follows Andys example.
Compare with * for pointesrs, i.e.
unsigned char * i,j;
may look like
unsigned char* i; unsigned char* j;
but is actually:
As you might have guessed from my replies, I also missed it initially!
"I never use the first one, precisely because someone quiclky scanning the code might make a bad assumption."
Absolutely. Plus all the other good reasons equivalent to always using the braces on an 'if' even when not strictly necessary...
in another c source file not main file, in this function nothing do,
You know that --- but the compiler doesn't. It has to assume that func1() modifies all the registers. So it can't assume that the value stored in a general-purpose register like R6 will still be the same after func1() has been called.
However, the compiler does not use registerbank as counter. Why?
Because it wouldn't work.
I read the Keil C51 user manual. I find that the REGUSE directive specifies which registers are modified by the specified function. So I add following code in func1() source file: #pragma asm $REGUSE func1() #pragma endasm and I get the assembly code:
61: MOV R7,#0C8H 62: ?C0002: 63: ; { 64: ; SOURCE LINE # 27 65: ; func1(); 66: ; SOURCE LINE # 28 C:0x0003 7FC8 MOV R7,#TMR2CN(0xC8) 67: LCALL func1 68: ; } 69: ; SOURCE LINE # 29 C:0x0005 120022 LCALL FUNC1(C:0022) 70: DJNZ R7,?C0002
and the problem fixed. Many thanks,everybody.
And you are sure that func1() really does not modify any registers?
Why was it a "problem" to you in the first place?
As Per says, your "solution" is storing up potentially far more real problems for you in the future...
Again: if you really need to worry about register-level detail like this, then you should be writing in assembler!