This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Stack Pointer Limitation

Hello,
The stack pointer for the chip I'm using is 8bits (address 256 bytes max). Is there any way to get around this limitation so I can have larger stack space? (without changing chips)
Regards,
KC

Parents
  • "The stack pointer for the chip I'm using is 8bits"

    That's the way the 8051 hardware is made!
    That's why C51 has to mess around with data overlaying, and thus has such difficulty with function pointers (look for the recent thread on the subject).

    Have you looked at the reentrant keyword?
    It'll give you a major performance hit, but could do what you want.

    Otherwise, you'll either have to rethink your design to work within the limitations of the 8051 architecture, or move to a different architecture more suited to your design!

Reply
  • "The stack pointer for the chip I'm using is 8bits"

    That's the way the 8051 hardware is made!
    That's why C51 has to mess around with data overlaying, and thus has such difficulty with function pointers (look for the recent thread on the subject).

    Have you looked at the reentrant keyword?
    It'll give you a major performance hit, but could do what you want.

    Otherwise, you'll either have to rethink your design to work within the limitations of the 8051 architecture, or move to a different architecture more suited to your design!

Children
  • Hello,
    In the Macro Assembler Manual (page 40) It states that PC is the identifier for the Program Counter. However I cant seem to use this identifier to get the value in PC.
    May I know how to obtain the current pragram couter value?
    Regards,
    KC

  • Dear Andrew Neil,
    When you use LCALL or ACALL to direct program to a function.
    May I know where the PC value is saved? and how does RET return restore the PC value when function ends?
    (if this value is saved to the stack, does it save the high order byte first or the low order byte?)
    I've also notice no difference in RET and RETI.
    Regards,
    KC


  • The LCALL and ACALL instructions store the program counter on the (hardware) stack, via the SP register. From the Intel MCS-51 instruction set manual:

    Operation: ACALL
    (PC)<- (PC)+ 2
    (SP)<- (SP) + 1
    ((SP)) <- (PC7.0)
    (SP)<- (SP) + 1
    ((SP))<- (PC15.8)
    (PC10.0)<- page address

    Operation: LCALL
    (PC) <-(PC) + 3
    (SP) <- (SP) + 1
    ((SP)) <- (PC7.0)
    (SP) <- (SP) + 1
    ((SP)) <- (PC15.8)
    (PC) <- addr15.0

    So, for what it's worth, the return addresses get pushed low byte first ("little endian"), but the address field of the instruction themselves are actually stored high byte first ("big endian").

    The hardware stack in the 8051 (SP pointing into internal RAM, usually "idata") is used pretty much only for return addresses, and occasionally for temporary storage. Parameters and local variables are not stored on the hardware stack, but instead assigned to fixed memory locations, which can be reused from function to function depending on the compiler/linker call tree overlay analysis. The "reentrant" keyword is used for functions that are recursive or that get called from multiple contexts where you really do need the usual C behavior of pushing parameters and auto variables onto a stack. This "simulated" stack does not use the SP register, but rather is built somewhere else in memory (depending on your memory model), possibly using the DPTR and xdata.

    The C51 manual discusses this briefly in "Function Parameters and the Stack" on page 119, "Reentrant Functions" on page 129, and the linker (Assembler/Utilities) manual "Overlaying Data Memory", page 261, and "Data Overlaying", page 280.

    The difference between RET and RETI is that RETI is "return from interrupt". The effect on the stack is the same; however, RETI also clears the interrupt logic in the 8051 and allows another interrupt of the current priority to execute. If a routine is an interrupt handler, it has to exit with RETI instead of RET. If a routine is not an interrupt handler, it should use RET. The C51 compiler knows which instruction to generate based on whether you declare the function as "interrupt" or not.

  • To program in assembler, you need to know & understand the processor's instruction set and artchitecture.
    You need to visit the following page & thoroughly read the 8051 "bible" documents before you do anything much else!
    http://www.8052.com/links.phtml
    (Look under the INTERESTING SITES heading)

  • Hello,

    If I use a simulated stack area by setting "XBPSTACK EQU 1" in XDATA memory.
    Should I write a function to save and load the whole "stack area" (DATA memory) each time I switch between tasks or functions?
    ( or is it possible to use both stack space at the same time? )

    I noticed that if you just use DATA memory area Keil will move the "starting SP position" up by placing variables below it (so no overlap).
    But for XBPSTACKTOP, we are setting the starting value (and it grows down), so wouldnt this cause an overlap later.

    Regards,
    KC

  • But for XBPSTACKTOP, we are setting the starting value (and it grows down), so wouldnt this cause an overlap later.

    Only if you use up all of the stack space.

    If you have 64K of XDATA, set the top of the XBPSTACK at 0xFFFF. That gives you 64K-(xdata variables) of stack space. Won't this be enough?

    Jon