??? 11/14/05 22:56 Read: times |
#103725 - Uh, no Responding to: ???'s previous message |
Jeff Corr said:
So if I place the push and pop data into the same subroutine, then the RET address will be located after the 6 bytes, and if I POP the 6 bytes before calling the RET, it should RET to the correct address? (Long as I push/pop within the same sub, should it not be okay?) Basically, you should not push a value onto the stack that you want to pop in a different function. Consider that the stack will start at address 08h unless you specifically set it to something else. If accumulator holds the value 24h and you immediately put it onto the stack, the stack will contain: IRAM address [08h]=24h If you then push the value 37h onto the stack, the stack will contain: IRAM address [08h]=24h IRAM address [09h]=37h If you pop a value off the stack, the value popped from the stack will be 37h (since it was the last value pushed on) and the stack will contain: IRAM address [08h]=24h Now, if you execute LCALL Subroutine and that instruction is at address 0616h the return address (the address of the next instruction after the subroutine returns with a RET instruction) is 0619h (since the LCALL instruction is 3 bytes long). So when you execute the LCALL insturction, the microcontroller will automatically push the value 19h onto the stack (the low byte of the return address) followed by the value 06h (the high byte of the return address). So when the "Subroutine" code executes, the stack is going to contain the following: IRAM address [08h]=24h (the first value you put on the stack) IRAM address [09h]=19h (low byte of return address) IRAM address [0Ah]=06h (high byte of return address) If your subroutine then POPs a value off the stack, it's going to be popping the high bye of the return address off the stack--not the value you pushed onto the stack. Thus after your subroutine pops the value off the stack, your stack will contain: IRAM address [08h]=24h (the first value you put on the stack) IRAM address [09h]=19h (low byte of return address) Now when your subroutine finishes it's going to execute a RET instruction to return to the instruction following the LCALL--if everything worked correctly, it would return to address 0619h. However in this case, since you popped the 06h byte off of the stack and your stack only contains the above contents, the microcontroller is going to pop a value of the stack (19h) which it will interpret as the high byte of the return address and then it's going to pop the next value off the stack (24h) and treat that as the low byte of the return address. So instead of your subroutine returning to the next instruction at 0619h, it's actually going to return to 1924h... and certainly crash your application. The 8051 stack really wasn't designed to pass values to subroutines. It can be done, but it's significantly more messy than just PUSHing and POPping. Regards, Craig Steiner |
Topic | Author | Date |
Stack pointer causing code to loop? | 01/01/70 00:00 | |
Try using a simulator | 01/01/70 00:00 | |
declaring variables | 01/01/70 00:00 | |
careful | 01/01/70 00:00 | |
push and pull | 01/01/70 00:00 | |
Correct | 01/01/70 00:00 | |
ah.. so if I change... | 01/01/70 00:00 | |
Uh, no | 01/01/70 00:00 | |
in same sub | 01/01/70 00:00 | |
Try a Ring Buffer | 01/01/70 00:00 | |
code changed so push/pops in same sub![]() | 01/01/70 00:00 |