Email: Password: Remember Me | Create Account (Free)

Back to Subject List

Old thread has been locked -- no new posts accepted in this thread
???
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


List of 11 messages in thread
TopicAuthorDate
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      

Back to Subject List