PUSH and POP for M2 Processors with Macros (X2 also)

techElder

Well-known member
#1
These PUSH/POP macros are for M2 processors but work for any processor. Future development will occur by adding multibyte and multiword PUSH/POP since by using POKE/PEEK multiple statements are reduced with more efficiency.

There is a demo program in the next post. Combine the two posts to make a complete PUSH/POP macro testing program.

Code:
[color=Green]' Implementing PUSH/POP for M2/X2 processors (X2 has built in PUSH/POP and PUSHRAM/POPRAM) ; "2018-03-28 05:49:17"
'  Creates a PUSH/POP stack at the highest RAM location (or anywhere else)
'  Stack location and size is based on PICAXE processor model
'  Handles stackpointer and upper/lower limits (STACKADDR, STACKSIZE) of RAM
'  Stack limits are imposed, but no exceptions/errors are made. Perhaps a RESET should occur?
'  Based on a PICAXE forum post by Tex (Texasclodhopper) with applied suggestions by hippy and lbenson
'  http://www.picaxeforum.co.uk/showthread.php?30659-PUSH-and-POP-for-M2-Processors&p=318493&viewfull=1#post318493

'  VERSION: 4 ; "2018-03-31 05:01:08" Added: sPush3B sPop3B STACKADDR3B STACKSIZE3B
'  VERSION: 3 ; "2018-03-30 15:30:31" ADDED: sPush3W sPop3W STACKADDR3W and STACKSIZE3W (see post about continued development)
'  VERSION: 2 ; "2018-03-29 09:17:48" CHANGED: STACKADDRW to -1 instead of -2
'  VERSION: 1 ; "2018-03-28 05:49:17"

' NOTE: The following directives should be placed high up in the program.[/color]
[color=Navy]#picaxe [/color][color=Black]20X2   [/color][color=Green]; Set the compiler mode, also the equivalent of #define xxx.
'#picaxe 20M2  ; Set the compiler mode, also the equivalent of #define xxx.
'#picaxe 18M2  ; Set the compiler mode, also the equivalent of #define xxx.

' combine the following with "#picaxe xxxx". This compiles the correct code for X2 or M2 processors. ; "2018-03-24 11:27:20"
' NOTE that the underscore "_" was added in the PE6 version editor. Probably leave it off for PE5.[/color]

[color=Navy]#IFDEF [/color][color=Blue]_20X2  [/color][color=Green]; "2018-03-28 05:49:17"
   [/color][color=Navy]#define [/color][color=Black]X2
   [/color][color=Navy]#define [/color][color=Black]MAXRAMADDR [/color][color=Navy][b]127
   [/b]#define [/color][color=Black]MINRAMADDR [/color][color=Navy][b]95[/b]
#ELSEIFDEF [/color][color=Blue]_28X2
   [/color][color=Navy]#define [/color][color=Black]X2
   [/color][color=Navy]#define [/color][color=Black]MAXRAMADDR [/color][color=Navy][b]255
   [/b]#define [/color][color=Black]MINRAMADDR [/color][color=Navy][b]191[/b]
#ELSEIFDEF [/color][color=Blue]_40X2
   [/color][color=Navy]#define [/color][color=Black]X2
   [/color][color=Navy]#define [/color][color=Black]MAXRAMADDR [/color][color=Navy][b]255
   [/b]#define [/color][color=Black]MINRAMADDR [/color][color=Navy][b]191[/b]
#ELSEIFDEF [/color][color=Blue]_08M2
   [/color][color=Navy]#define [/color][color=Blue]M2
   [/color][color=Navy]#define [/color][color=Black]MAXRAMADDR [/color][color=Navy][b]127
   [/b]#define [/color][color=Black]MINRAMADDR [/color][color=Navy][b]95[/b]
#ELSEIFDEF [/color][color=Blue]_18M2
   [/color][color=Navy]#define [/color][color=Blue]M2
   [/color][color=Navy]#define [/color][color=Black]MAXRAMADDR [/color][color=Navy][b]511
   [/b]#define [/color][color=Black]MINRAMADDR [/color][color=Navy][b]447[/b]
#ELSEIFDEF [/color][color=Blue]_14M2
   [/color][color=Navy]#define [/color][color=Blue]M2
   [/color][color=Navy]#define [/color][color=Black]MAXRAMADDR [/color][color=Navy][b]511
   [/b]#define [/color][color=Black]MINRAMADDR [/color][color=Navy][b]447[/b]
#ELSEIFDEF [/color][color=Blue]_20M2
   [/color][color=Navy]#define [/color][color=Blue]M2
   [/color][color=Navy]#define [/color][color=Black]MAXRAMADDR [/color][color=Navy][b]511
   [/b]#define [/color][color=Black]MINRAMADDR [/color][color=Navy][b]447[/b]
#ELSE
   #error "Must define processor!"
#ENDIF[/color]

[color=Blue]symbol STACKADDR     [/color][color=DarkCyan]= [/color][color=Black]MAXRAMADDR            [/color][color=Green]; stack grows down from maximum RAM established in Directives[/color]
[color=Blue]symbol STACKSIZE     [/color][color=DarkCyan]= [/color][color=Black]MINRAMADDR            [/color][color=Green]; stack can grow down to this minimum RAM established in Directives[/color]
[color=Blue]symbol STACKADDRW    [/color][color=DarkCyan]= [/color][color=Blue]STACKADDR [/color][color=DarkCyan]- [/color][color=Navy][b]1         [/b][/color][color=Green]; stack address for WORDs (changed from 2); "2018-03-29 13:56:55"[/color]
[color=Blue]symbol STACKSIZEW    [/color][color=DarkCyan]= [/color][color=Blue]STACKSIZE [/color][color=DarkCyan]+ [/color][color=Navy][b]1         [/b][/color][color=Green]; stack size for WORDs[/color]
[color=Blue]symbol STACKADDR3W   [/color][color=DarkCyan]= [/color][color=Blue]STACKADDR [/color][color=DarkCyan]- [/color][color=Navy][b]5         [/b][/color][color=Green]; stack address for 3 WORDs ; "2018-03-30 15:30:31"[/color]
[color=Blue]symbol STACKSIZE3W   [/color][color=DarkCyan]= [/color][color=Blue]STACKSIZE [/color][color=DarkCyan]+ [/color][color=Navy][b]5         [/b][/color][color=Green]; stack size for 3 WORDs ; "2018-03-30 15:30:31"[/color]
[color=Blue]symbol STACKADDR3B   [/color][color=DarkCyan]= [/color][color=Blue]STACKADDR [/color][color=DarkCyan]- [/color][color=Navy][b]2         [/b][/color][color=Green]; stack address for 3 BYTEs ; "2018-03-31 05:01:08"[/color]
[color=Blue]symbol STACKSIZE3B   [/color][color=DarkCyan]= [/color][color=Blue]STACKSIZE [/color][color=DarkCyan]+ [/color][color=Navy][b]2         [/b][/color][color=Green]; stack size for 3 BYTEs ; "2018-03-31 05:01:08"[/color]

[color=Navy]#IFDEF [/color][color=Black]X2
   [/color][color=Blue]symbol [/color][color=Purple]sPtr             [/color][color=DarkCyan]= [/color][color=Purple]b55             [/color][color=Green]; highest BYTE variable[/color]
[color=Navy]#ENDIF
#IFDEF [/color][color=Blue]M2
   symbol [/color][color=Purple]sPtr             [/color][color=DarkCyan]= [/color][color=Purple]w13             [/color][color=Green]; highest WORD variable (due to 512 RAM locations)[/color]
[color=Navy]#ENDIF

#macro [/color][color=Black]sPushB[/color][color=Blue]([/color][color=Black]bVar[/color][color=Blue]) [/color][color=Green]; "2018-03-29 09:17:48"
   [/color][color=Blue]if [/color][color=Purple]sPtr [/color][color=DarkCyan]> [/color][color=Blue]STACKSIZE then                  [/color][color=Green]; stack limit not reached
      [/color][color=Blue]poke [/color][color=Purple]sPtr[/color][color=Black], bVar                        [/color][color=Green]; put the value into the stack
      [/color][color=Blue]dec [/color][color=Purple]sPtr                               [/color][color=Green]; set the next stack pointer
   'else
      ' what to do if sPtr <= STACKSIZE?????
   [/color][color=Blue]endif[/color]
[color=Navy]#endm

#macro [/color][color=Black]sPushW[/color][color=Blue]([/color][color=Black]wVar[/color][color=Blue]) [/color][color=Green]; "2018-03-29 09:17:48"
   [/color][color=Blue]if [/color][color=Purple]sPtr [/color][color=DarkCyan]> [/color][color=Blue]STACKSIZEW then                 [/color][color=Green]; stack limit not reached
      [/color][color=Blue]dec [/color][color=Purple]sptr                               [/color][color=Green]; make room for WORD
      [/color][color=Blue]poke [/color][color=Purple]sPtr[/color][color=Black], [/color][color=Blue]WORD [/color][color=Black]wVar                   [/color][color=Green]; put the value into the stack (LE)
      [/color][color=Blue]dec [/color][color=Purple]sPtr                               [/color][color=Green]; set the next stack pointer after WORD
   'else
      ' what to do if sPtr <= STACKSIZEW?????
   [/color][color=Blue]endif[/color]
[color=Navy]#endm

#macro [/color][color=Black]sPopB[/color][color=Blue]([/color][color=Black]bVar[/color][color=Blue]) [/color][color=Green]; "2018-03-29 09:17:48"
   [/color][color=Blue]if [/color][color=Purple]sPtr [/color][color=DarkCyan]< [/color][color=Blue]STACKADDR then                  [/color][color=Green]; stack start reached
      [/color][color=Blue]inc [/color][color=Purple]sPtr
      [/color][color=Blue]peek [/color][color=Purple]sPtr[/color][color=Black], bVar                        [/color][color=Green]; put the value into the variable
      's_w0=$99:poke sPtr, s_w0                  ; put the value into the variable
   'else
      ' what to do if sPtr => STACKADDR?????
   [/color][color=Blue]endif[/color]
[color=Navy]#endm

#macro [/color][color=Black]sPopW[/color][color=Blue]([/color][color=Black]wVar[/color][color=Blue]) [/color][color=Green]; "2018-03-29 09:17:48"
   [/color][color=Blue]if [/color][color=Purple]sPtr [/color][color=DarkCyan]< [/color][color=Blue]STACKADDRW then                 [/color][color=Green]; stack start reached
      [/color][color=Blue]inc [/color][color=Purple]sPtr                               [/color][color=Green]; set the stack pointer for WORD
      [/color][color=Blue]peek [/color][color=Purple]sPtr[/color][color=Black], [/color][color=Blue]WORD [/color][color=Black]wVar                   [/color][color=Green]; put the value into the variable
      [/color][color=Blue]inc [/color][color=Purple]sPtr                               [/color][color=Green]; set the next stack pointer after WORD
      's_w0=$FFFF:poke sPtr, WORD s_w0                  ; put the value into the variable
   'else
      ' what to do if sPtr => STACKADDRW?????
   [/color][color=Blue]endif[/color]
[color=Navy]#endm[/color]
NOTE: Be aware that I've only tested this with the demo program which is not exactly a real world example.
 
Last edited:

techElder

Well-known member
#2
PUSH and POP for M2 Processors with Macros (X2 also) DEMO Program

Demonstration program. Combine with previous macro definitions.

' NOTE: Be aware that I've only tested these macros with the demo program which is not exactly a real world example.

Code:
[color=Green]'---------------------------
[PLAIN]'------[ DEMO BEGINS ]------[/PLAIN]
'---------------------------[/color]

[color=Black]sPtr [/color][color=DarkCyan]= [/color][color=Black]STACKADDR                             [/color][color=Green]; initialize the stack pointer

;b0 = 255
;b1 = 255
;b2 = 255
;b3 = 255
;
;sPushB(b0)
;sPushB(b1)
;sPushB(b2)
;sPushB(b3)
;
;b0 = 254
;b1 = 127
;b2 = 64
;b3 = 32
;
;sPopB(b3)
;sPopB(b2)
;sPopB(b1)
;sPopB(b0)
;
;b0 = 254
;b1 = 127
;b2 = 64
;b3 = 32
;
;sPushB(b0)
;sPushB(b1)
;sPushB(b2)
;sPushB(b3)
;
;b0 = 255
;b1 = 255
;b2 = 255
;b3 = 255
;
;sPushB(b0)
;sPushB(b1)
;sPushB(b2)
;sPushB(b3)
;
;b0 = 1
;b1 = 2
;b2 = 3
;b3 = 4
;
;sPushB(b0)
;sPushB(b1)
;sPushB(b2)
;sPushB(b3)
;
;sPopB(b3)
;sPopB(b2)
;sPopB(b1)
;sPopB(b0)
;
;sPopB(b3)
;sPopB(b2)
;sPopB(b1)
;sPopB(b0)
;
;sPopB(b3)
;sPopB(b2)
;sPopB(b1)
;sPopB(b0)[/color]

[color=Black]sPtr [/color][color=DarkCyan]= [/color][color=Black]STACKADDR                             [/color][color=Green]; initialize the stack pointer

;' words group 1
;w0 = $88AA
;w1 = $88BB
;w2 = $88CC
;w3 = $88DD
;
;sPushW(w0)
;sPushW(w1)
;sPushW(w2)
;sPushW(w3)
;
;' words group 2
;w0 = $880A
;w1 = $880B
;w2 = $880C
;w3 = $880D
;
;sPushW(w0)
;sPushW(w1)
;sPushW(w2)
;sPushW(w3)
;
;' bytes group 3
;b0 = 254
;b1 = 127
;b2 = 64
;b3 = 32
;
;sPushB(b0)
;sPushB(b1)
;sPushB(b2)
;sPushB(b3)
;
;' words group 4
;w4 = $88A0
;w5 = $88B0
;w6 = $88C0
;w7 = $88D0
;
;sPushW(w4)
;sPushW(w5)
;sPushW(w6)
;sPushW(w7)
;
;' pop words group 4
;sPopW(w7)
;sPopW(w6)
;sPopW(w5)
;sPopW(w4)
;
;' pop bytes group 3
;sPopB(b3)
;sPopB(b2)
;sPopB(b1)
;sPopB(b0)
;
;' pop words group 2
;sPopW(w3)
;sPopW(w2)
;sPopW(w1)
;sPopW(w0)
;
;' pop words group 1
;sPopW(w3)
;sPopW(w2)
;sPopW(w1)
;sPopW(w0)
;
' intermingle words and bytes
' bytes group A
;b0 = 254
;b1 = 127
;b2 = 64
;b3 = 32
;
;' words group B
;w4 = $88A0
;w5 = $88B0
;w6 = $88C0
;w7 = $88D0
;
;' push bytes then words group A then B
;sPushB(b0)
;sPushW(w4)
;sPushB(b1)
;sPushW(w5)
;sPushB(b2)
;sPushW(w6)
;sPushB(b3)
;sPushW(w7)
;' push bytes then words group A then B
;sPushB(b0)
;sPushW(w4)
;sPushB(b1)
;sPushW(w5)
;sPushB(b2)
;sPushW(w6)
;sPushB(b3)
;sPushW(w7)
;
;' pop words then bytes group B then A
;sPopW(w7)
;sPopB(b3)
;sPopW(w6)
;sPopB(b2)
;sPopW(w5)
;sPopB(b1)
;sPopW(w4)
;sPopB(b0)
;' pop words then bytes group B then A
;sPopW(w7)
;sPopB(b3)
;sPopW(w6)
;sPopB(b2)
;sPopW(w5)
;sPopB(b1)
;sPopW(w4)
;sPopB(b0)


;b0 = 254
;b1 = 127
;b2 = 64
;b3 = 32
;sPush3B(b1,b2,b3) ; "2018-03-31 05:01:08"
;b0 = 1
;b1 = 2
;b2 = 3
;b3 = 4
;sPop3B(b1,b2,b3) ; "2018-03-31 05:01:08"

;' words group 2 ; "2018-03-30 15:30:31"
;w0 = $880A
;w1 = $880B
;w2 = $880C
;w3 = $880D
;sPush3W(w1,w2,w3)
;' words group B ; "2018-03-30 15:30:31"
;w4 = $77A0
;w5 = $77B0
;w6 = $77C0
;w7 = $77D0
;sPush3W(w5,w6,w7)
;
;' exchange 3 word sets with each other ; "2018-03-30 15:30:31"
;sPop3W(w1,w2,w3)
;sPop3W(w5,w6,w7)[/color]

[color=Blue]end[/color]
 
Last edited:

techElder

Well-known member
#3
RESERVED FOR FUTURE DEVELOPMENT OF PUSH/POP MACROS

Multiple word PUSH/POP

Code:
[color=Navy]#macro [/color][color=Black]sPush3W[/color][color=Blue]([/color][color=Black]wVar1,wVar2,wVar3[/color][color=Blue]) [/color][color=Green]; "2018-03-30 15:30:31"
   [/color][color=Blue]if [/color][color=Black]sPtr [/color][color=DarkCyan]> [/color][color=Black]STACKSIZE3W [/color][color=Blue]then                [/color][color=Green]; stack limit not reached
      [/color][color=Black]sPtr [/color][color=DarkCyan]= [/color][color=Black]sPtr [/color][color=DarkCyan]- [/color][color=Navy][b]5                        [/b][/color][color=Green]; make room for WORDs
      [/color][color=Blue]poke [/color][color=Black]sPtr, [/color][color=Blue]WORD [/color][color=Black]wVar1, [/color][color=Blue]WORD [/color][color=Black]wVar2, [/color][color=Blue]WORD [/color][color=Black]wVar3 [/color][color=Green]; put the value into the stack (LE)
      [/color][color=Blue]dec [/color][color=Black]sPtr                               [/color][color=Green]; set the next stack pointer after WORD
   'else
      ' what to do if sPtr <= STACKSIZE3W?????
   [/color][color=Blue]endif[/color]
[color=Navy]#endm

#macro [/color][color=Black]sPop3W[/color][color=Blue]([/color][color=Black]wVar1,wVar2,wVar3[/color][color=Blue]) [/color][color=Green]; "2018-03-30 15:30:31"
   [/color][color=Blue]if [/color][color=Black]sPtr [/color][color=DarkCyan]< [/color][color=Black]STACKADDR3W [/color][color=Blue]then                [/color][color=Green]; stack start reached
      [/color][color=Blue]inc [/color][color=Black]sPtr                               [/color][color=Green]; set the stack pointer for WORD
      [/color][color=Blue]peek [/color][color=Black]sPtr, [/color][color=Blue]WORD [/color][color=Black]wVar1, [/color][color=Blue]WORD [/color][color=Black]wVar2, [/color][color=Blue]WORD [/color][color=Black]wVar3 [/color][color=Green]; put the value into the variable
      [/color][color=Black]sPtr [/color][color=DarkCyan]= [/color][color=Black]sPtr [/color][color=DarkCyan]+ [/color][color=Navy][b]5                        [/b][/color][color=Green]; set the next stack pointer after WORD
   'else
      ' what to do if sPtr => STACKADDR3W?????
   [/color][color=Blue]endif[/color]
[color=Navy]#endm[/color]
Multiple byte PUSH/POP

Code:
[color=Navy]#macro [/color][color=Black]sPush3B[/color][color=Blue]([/color][color=Black]bVar1,bVar2,bVar3[/color][color=Blue]) [/color][color=Green]; "2018-03-31 05:01:08"
   [/color][color=Blue]if [/color][color=Purple]sPtr [/color][color=DarkCyan]> [/color][color=Blue]STACKSIZE3B then                [/color][color=Green]; stack limit not reached
      [/color][color=Purple]sPtr [/color][color=DarkCyan]= [/color][color=Purple]sPtr [/color][color=DarkCyan]- [/color][color=Navy][b]2                        [/b][/color][color=Green]; make room for WORDs
      [/color][color=Blue]poke [/color][color=Purple]sPtr[/color][color=Black], bVar1, bVar2, bVar3 [/color][color=Green]; put the value into the stack (LE)
      [/color][color=Blue]dec [/color][color=Purple]sPtr                               [/color][color=Green]; set the next stack pointer after WORD
   'else
      ' what to do if sPtr <= STACKSIZE3B?????
   [/color][color=Blue]endif[/color]
[color=Navy]#endm

#macro [/color][color=Black]sPop3B[/color][color=Blue]([/color][color=Black]bVar1,bVar2,bVar3[/color][color=Blue]) [/color][color=Green]; "2018-03-31 05:01:08"
   [/color][color=Blue]if [/color][color=Purple]sPtr [/color][color=DarkCyan]< [/color][color=Blue]STACKADDR3B then                [/color][color=Green]; stack start reached
      [/color][color=Blue]inc [/color][color=Purple]sPtr                               [/color][color=Green]; set the stack pointer for WORD
      [/color][color=Blue]peek [/color][color=Purple]sPtr[/color][color=Black], bVar1, bVar2, bVar3 [/color][color=Green]; put the value into the variable
      [/color][color=Purple]sPtr [/color][color=DarkCyan]= [/color][color=Purple]sPtr [/color][color=DarkCyan]+ [/color][color=Navy][b]2                        [/b][/color][color=Green]; set the next stack pointer after WORD
   'else
      ' what to do if sPtr => STACKADDR3B?????
   [/color][color=Blue]endif[/color]
[color=Navy]#endm[/color]
 
Last edited:

techElder

Well-known member
#4
This is a document explaining the operation of the PUSH/POP stack for the PICAXE M2 processors. It works on other processors, also. The X2 processors already have PUSH/POP and PUSHRAM/POPRAM statements built in, but they aren’t as robust as this stack design.

Each processor has a certain amount and configuration of available RAM depending on the underlying PIC’s capability. This is called a “stack”, because RAM is released with each POP of the stack. This stack design is addressed “top-down”; from the maximum available RAM location to an allocated limit at a lower address.

There are variations in the stack based on how much RAM is available to be used. The stack starts at the address of the maximum RAM available for a particular processor. This is set with MAXRAMADDR in the initial directives. The stack design allows for each procedure to verify whether there is RAM available for the stack to use by limiting the maximum stack size. This is set with MINRAMADDR in the initial directives. If there isn’t room for the current PUSH operation, the operation will be ignored. (Modifications of this behavior are possible in each procedure.) To obtain a 32 byte stack, subtract 32 from MAXRAMADDR to get MINRAMADDR. MINRAMADDR is not used to create the stack, but is used to test for the end of the stack with STACKSIZE (and its variations.) STACKADDR is created to allow procedures to test for the beginning of the stack.

There are variations in the procedures based on whether an operation is to be performed with variables of type BYTE, WORD, MULTIPLE BYTES or MULTIPLE WORDS. (There is code efficiency in using the multiple byte procedures if the program design can take advantage of that.) The most basic procedure is to PUSH onto the stack and POP from the stack. As in all stack designs, the user has to make sure that what is PUSHED onto the stack is POPPED off of the stack in the correct order. There are corresponding PUSH and POP procedures for each variable type. (The multiple byte/word PUSH and POP procedures are treated the same as a single byte/word procedure as far as PUSH and POP order.)

PUSHING A BYTE ONTO THE STACK

The sPtr variable is used as the pointer for the stack. That variable is adjusted to indicate where the next byte will be placed. Initially, sPtr is set to the top of the stack.
Procedure sPushB(bVar) checks to see if sPtr is greater than the STACKSIZE, which means that (if true) sPtr has a RAM location to put the byte bVar. Then sPtr is adjusted to point to the next location where the next PUSH operation can be performed. It is important to note that if the current PUSH operation was performed at the location just above STACKSIZE, then sPtr is now pointed to STACKSIZE which is not a writeable location by design. For the next PUSH operation sPtr is checked to see if it is greater than the STACKSIZE. That will be false, and the operation will terminate without doing anything to the RAM location STACKSIZE.

POPPING A BYTE FROM THE STACK

Procedure sPopB(bVar) checks to see if sPtr is less than the STACKADDR, which means that (if true) sPtr has been adjusted to the next RAM location ready for the next PUSH operation, and there is a BYTE available to be POPPED from the stack by this procedure. The pointer (sPtr) has to be adjusted to point where the BYTE to be POPPED is and not to the next available location. It is important to note that the POPPED location has now become the location for the next PUSH operation as needed.

PUSHING A WORD ONTO THE STACK

A word is 2 bytes, so adjustment is made for that by creating an additional reference to STACKSIZE called STACKSIZEW. Also, the STACKADDR has an additional reference in STACKADDRW.

Procedure sPushW(wVar) checks to see if sPtr is greater than the STACKSIZEW, which means that (if true) sPtr has RAM locations available to put the word wVar into. Next, sPtr is adjusted by one byte to point to the location where the word's LSB will placed. The MSB will be placed one byte higher than that (“Little Endian” [LE] format.) Then sPtr is adjusted to point to the next location where the next PUSH operation can be performed.

POPPING A WORD FROM THE STACK

Procedure sPopW(wVar) checks to see if sPtr is less than the STACKADDRW, which means that (if true) sPtr has been adjusted to the next RAM location ready for the next PUSH operation, and there is a WORD available to be POPPED from the stack by this procedure. The pointer (sPtr) has to be adjusted to point where the WORD to be POPPED is, and after the POP operation with two bytes moving, sPtr is once again adjusted to point to the next available RAM location where the next PUSH operation can be performed.

PUSHING MULTIPLE WORDS ONTO THE STACK

A multiple word PUSH is extra bytes, so adjustment is made for that by creating additional references to STACKSIZE and STACKADDR. In this example, using a three word procedure, the references are called STACKSIZE3W and STACKADDR3W.

Procedure sPush3W(wVar1,wVar2,wVar3) checks to see if sPtr is greater than the STACKSIZE3W, which means that (if true) sPtr has RAM locations available to put the words wVar1-3 into. Next, sPtr is adjusted by 5 bytes to point to the location where the first word's LSB will placed. The MSB will be placed one byte higher than that (“Little Endian” [LE] format.) The second and third word's bytes are placed after that. Then sPtr is adjusted to point to the next location where the next PUSH operation can be performed. It is important to note that this procedure is moving three words, but they are moved in one operation as far as the PUSH/POP order is concerned.

POPPING MULTIPLE WORDS FROM THE STACK

Procedure sPop3W(wVar1,wVar2,wVar3) checks to see if sPtr is less than the STACKADDR3W, which means that (if true) sPtr has been adjusted to the next RAM location ready for the next PUSH operation, and there are multiple WORDs available to be POPPED from the stack by this procedure. The pointer (sPtr) has to be adjusted to point where the WORD to be POPPED is, and after the POP operation with three words moving, sPtr is once again adjusted by 5 bytes to point to the next available RAM location where the next PUSH operation can be performed.

PUSHING MULTIPLE BYTES ONTO THE STACK

A multiple byte PUSH is extra bytes, so adjustment is made for that by creating additional references to STACKSIZE and STACKADDR. In this example, using a three byte procedure, the references are called STACKSIZE3B and STACKADDR3B.

Procedure sPush3B(bVar1,bVar2,bVar3) checks to see if sPtr is greater than the STACKSIZE3B, which means that (if true) sPtr has RAM locations available to put the bytes bVar1-3 into. Next, sPtr is adjusted by 2 bytes to point to the location where the first byte will placed. The second and third bytes are placed after that. Then sPtr is adjusted to point to the next location where the next PUSH operation can be performed. It is important to note that this procedure is moving three bytes, but they are moved in one operation as far as the PUSH/POP order is concerned.

POPPING MULTIPLE BYTES FROM THE STACK

Procedure sPop3B(bVar1,bVar2,bVar3) checks to see if sPtr is less than the STACKADDR3B, which means that (if true) sPtr has been adjusted to the next RAM location ready for the next PUSH operation, and there are multiple BYTEs available to be POPPED from the stack by this procedure. The pointer (sPtr) has to be adjusted to point where the BYTE to be POPPED is, and after the POP operation with three bytes moving, sPtr is once again adjusted by 2 bytes to point to the next available RAM location where the next PUSH operation can be performed.

WRITTEN DOCUMENTATION

Please download this PDF file containing the above document, but it also contains multiple diagrams of the stack as described above.

View attachment PUSHPOPexplanation2018-03-30-2.pdf
 
Last edited:
Top