Push
Syntax
Push Variable, {Variable, Variable etc}
Overview
Place a single variable or multiple variables onto the microcontroller’s stack.
Parameters
Variable is a user defined variable of type Bit, Byte, Word, Dword, Float, Double, Arrays, String, or constant value.
The amount of bytes pushed on to the stack varies with the variable type used. The list below shows how many bytes are pushed for a particular variable type, and their order. The microcontroller’s stack is word orientated, therefore all operations are accomplished using 16-bits.
Bit 2 Bytes are pushed that hold the condition of the bit. Byte 2 Bytes are pushed.
Byte Array
2 Bytes are pushed. Word 2 Bytes are pushed. High Byte then Low Byte.
Word Array
2 Bytes are pushed. High Byte then Low Byte.
Dword Array
4 Bytes are pushed. High Byte, Mid2 Byte, Mid1 Byte then Low Byte.
Float Array
4 Bytes are pushed. High Byte, Mid2 Byte, Mid1 Byte then Low Byte.
Dword
4 Bytes are pushed. High Byte, Mid2 Byte, Mid1 Byte then Low Byte.
Float
4 Bytes are pushed. High Byte, Mid2 Byte, Mid1 Byte then Low Byte.
Double
8 Bytes are pushed. High Byte, Midx Bytes, then Low Byte.
String
2 Bytes are pushed. High Byte then Low Byte that point to the start address of the String in memory.
Constant
Amount of bytes varies according to the value pushed. High Byte first.
Example 1
' Push two variables on to the stack then retrieve them
Device = 24HJ128GP502
' Select the device to compile for
Declare Xtal = 16
Declare Stack_Size = 90
' Increase the stack for holding extra words
Dim MyWord as Word
' Create a Word variable
Dim MyDword as Dword
' Create a Dword variable
MyWord = 1234
' Load the Word variable with a value
MyDword = 567890
' Load the Dword variable with a value
Push MyWord, MyDword
' Push the Word variable then the Dword variable
Clear MyWord
' Clear the Word variable
Clear MyDword
' Clear the Dword variable
Pop MyDword, MyWord
' Pop the Dword variable then the Word variable
Print Dec MyWord, " ", Dec MyDword ' Display the variables as decimal
Example 2
' Push a String on to the stack then retrieve it
Device = 24HJ128GP502
' Select the device to compile for
Declare Xtal = 16
Declare Stack_Size = 80
' Increase the stack for holding extra words
Dim SourceString as String * 20 ' Create a String variable
Dim DestString as String * 20 ' Create another String variable
SourceString = "Hello World" ' Load the String variable with characters
Push SourceString
' Push the String variable's address
Pop DestString
' Pop the previously pushed String into DestString
Print DestString
' Display the string, which will be "Hello World"
Formatting a Push.
Each variable type, and more so, constant value, will push a different amount of bytes on to the stack. This can be a problem where values are concerned because it will not be known what size variable is required in order to Pop the required amount of bytes from the stack. For example, the code below will push a constant value of 200 onto the stack, which requires 2 bytes (remember, the stack is 16-bit orientated).
Push 200
All well and good, but what if the recipient popped variable is of a Dword or Float type.
Pop MyWord
Popping from the stack into a Dword variable will actually pull 4 bytes from the stack, however, the code above has only pushed two bytes, so the stack will become out of phase with the values or variables previously pushed. This is not really a problem where variables are concerned, as each variable has a known byte count and the user knows if a Word is pushed, a Word should be popped.
The answer lies in using a formatter preceding the value or variable pushed, that will force the amount of bytes loaded on to the stack. The formatters are Byte, Word, Dword or Float.
The Byte formatter will force any variable or value following it to push only 1 word to the stack.
Push Byte 12345
The Word formatter will force any variable or value following it to push only 1 word to the stack:
Push Word 123
The Dword formatter will force any variable or value following it to push only 2 words to the stack: -
Push Dword 123
The Float formatter will force any variable or value following it to push only 2 words to the stack, and will convert a constant value into the 2-word floating point format: -
Push Float 123.1
The Double formatter will force any variable or value following it to push only 4 words to the stack, and will convert a constant value into the 4-word 64-bit floating point format: -
Push Double 123.1
So for the Push of 200 code above, you would use: -
Push Word 200
In order for it to be popped back into a Word variable, because the push would be the high byte of 200, then the low byte.
If using the multiple variable Push, each parameter can have a different formatter preceding it.
Push Word 200, Dword 1234, Float 1234
Note that if a floating point value is pushed, 2 words will be placed on the stack because this is a known format.
What is a Stack?
Unlike the 8-bit PIC® microcontrollers, the PIC24® and dsPIC33® devices have a true stack, which is an area of RAM allocated for temporary data storage and call-return address's.
The stack is always present within a PIC24® or dsPIC33® device and is located at the end of the variable RAM. The microcontroller uses it for call and return addresses, but it can also be used for temporary storage of variables. The stack defaults to 60 words, but can be increased or decreased by issuing the Stack_Size Declare.
Declare Stack_Size = 200
The above line of code will increase the stack to 200 words.
Taking the above line of code as an example, we can examine what happens when a variable is pushed on to the 200 word stack, and then popped off again.
Pushing.
When a Word variable is pushed onto the stack, the memory map would look like the diagram below: -
End Of Stack Empty RAM
~ ~
~ ~
Empty RAM
Start Of Stack Contents of the Word Variable
Because each element of the stack is 16-bit wide, the contents of the Word variable are placed directly into it. The stack grows in an upward direction whenever a Push is implemented, which means it shrinks back down whenever a Pop is implemented. If we were to Push a Dword variable on to the stack as well as the Word variable, the stack memory would look like: -
End Of Stack Empty RAM
~ ~
~ ~
Empty RAM
Contents of the Word Variable
Contents of the High Word of the Dword Variable
Start Of Stack Contents of the Low Word of the Dword Variable
Popping.
When using the Pop command, the same variable type that was pushed last must be popped first, or the stack will become out of phase and any variables that are subsequently popped will contain invalid data, and there is a possibility that the microcontroller will cause an exception.
For example, using the above analogy, we need to Pop a Dword variable first. The Dword variable will be popped Low Word first, then the High Word. This will ensure that the same value pushed will be reconstructed correctly when placed into its recipient variable. After the Pop, the stack memory map will look like: -
End Of Stack Empty RAM
~ ~
~ ~
Empty RAM
Start Of Stack Contents of the Word Variable
If a Word variable was then popped, the stack will be empty, unless it already contains call/return address’s. Now what if we popped a Dword variable instead of the required Word variable? the stack would underflow by one word and definitely cause an exception. The same is true if the stack overflows.
Technical Details of Stack implementation.
The stack implemented by the PIC24® and dsPIC33® microcontroller’s is known as an Incrementing Last-In First-Out Stack. Incrementing because it grows upwards in memory. Last-In First-Out because the last variable pushed, will be the first variable popped.
The stack is not circular in operation, so that a stack underflow or overflow will cause an exception to be triggered.
Whenever a variable is popped from the stack, the stack's memory is not actually cleared, only the stack pointer is moved (WREG15). Therefore, the above diagrams are not quite true when they show empty RAM, but unless you have use of the remnants of the variable, it should be considered as empty, and will be overwritten by the next Push command.