Hello, why is the simple code below assembled wrong? The disassembly copies the same value from the same memory location 0x06 to tp(n). (MOV @R0,0x06)
Thanks for Help Christian Tauschek
MY WRITTEN CODE: unsigned char tp[20]; for (n = 19; n > 0 ; n--) { tp[n] = tp[n-1]; }
__________________________________________ WRONG DISASSEMBLY:
46: for (n = 19; n > 0 ; n--) { C:0x08CA 7F13 MOV R7,#0x13 47: tp[n] = tp[n-1]; C:0x08CC 7421 MOV A,#0x21 C:0x08CE 2F ADD A,R7 C:0x08CF F8 MOV R0,A C:0x08D0 E6 MOV A,@R0 C:0x08D1 FE MOV R6,A C:0x08D2 7422 MOV A,#tp(0x22) C:0x08D4 2F ADD A,R7 C:0x08D5 F8 MOV R0,A C:0x08D6 A606 MOV @R0,0x06 48: } C:0x08D8 DFF2 DJNZ R7,C:08CC __________________________________________
MY uVISION3: IDE-Version: µVision3 V3.80 Copyright (c) Keil Elektronik GmbH / Keil Software, Inc. 1995 - 2009
License Information: Christian Tauschek Tauschek LIC=----
Tool Version Numbers: Toolchain: PK51 Prof. Develpers Kit Version: 8.18 Toolchain Path: C:\Keil\C51\BIN\ C Compiler: C51.Exe V8.18 Assembler: A51.Exe V8.01 Linker/Locator: BL51.Exe V6.20 Librarian: LIB51.Exe V4.24 Hex Converter: OH51.Exe V2.6 CPU DLL: S8051.DLL V3.65 Dialog DLL: DP51.DLL V2.54
why is the simple code below assembled wrong?
Because it isn't. There's nothing wrong with that code. Dan already told you why:
The disassembly copies the same value from the same memory location 0x06 to tp(n). (MOV @R0,0x06)
Memory location 0x06 is the location of (the bank 0 rendition of) the R6 register, so there is nothing wrong with this: it copies the content of R6 (which at this moment holds tp[n-1]) to where R0 currently points (tp[n])
So whatever the actual problem is, this code snippet is not it.
Thanks for your answers, but i still have the problem. I tried to shorten the code as much as possible. If you replace the function call "get_taste()" with the code within the get_taste-function-code then it works ok. But i don't understand why. There should be no difference. Christian Tauschek
unsigned char tp[2]; unsigned char n, r1; void timer1_isr(void) interrupt 3 using 1 { TL1 = 0xef; TH1 = 0xd8; // if i replace this call "get_taste()" with // the get_taste-code below, then it works ok get_taste(); } void get_taste(void) { tp[0x00] = 0x0a; tp[0x01] = 0x0b; n = 0x01; tp[n] = tp[n - 1]; // there is the MISTAKE // now i expect the value 0x0a in r1, but r1 // has the value 0x00 r1 = tp[n]; }
Note the use of "using 1" which selects a specific register bank.
But how would get_taste() know that you call it from an ISR that is "using 1"?
When you mix code using different register banks, then you can get these effects.
Memory location 6 is always at the same place, but the definition of R6 will change depending on the currently used register set (the "using" part).
void get_taste(void) { tp[0x00] = 0x0a; tp[0x01] = 0x0b; n = 0x01; tp[n] = tp[n - 1]; // there is the MISTAKE
No. That is only where the mistake caused elsewhere finally bites.
There is a pair of places where the mistake is: you call a function from an ISR qualified "using 1", but the called function itself is not qualified "using 1". That combination is a monstrously big NO-NO.
Hello all, thanks for answers. Now, without "using 1", it works fine. I caused the mistake.
Christian Tauschek
However, using significantly reduces the overhead in your ISR - so you should really know how to use it properly (even if it isn't needed in this particular case)
See http://www.keil.com/support/man/docs/c51/c51_le_regbankaccess.htm for details.
Also: http://www.keil.com/support/man/docs/c51/c51_le_regbankspec.htm and the linked knowledgebase articles.