PDA

View Full Version : Software Stack



yasser hassani
- 13th December 2007, 09:50
Hi anybody
Several days ago I found a program that was about 48 level Software Stack on a 14-bit Core PIC.
http://www.pbpgroup.com/modules/wfsection/article.php?articleid=14
That's really great but I have some questions about it.
1- It includes an .inc file as below:

'************************************************* ***************
'* Name : swStack.inc *
'* Author : Darrel Taylor *
'* Date : 11/26/2003 *
'* Version : 1.0 *
'* Notes : Software Stack for PicBasic Pro *
'* : Allows up to 48 level Gosub Stack *
'* : on a PIC with an 8 level Hardware Stack *
'* : Tested with 16F877 on a LAB-X2 *
'************************************************* ***************
'* Many thanks to John Barrat for solving the *
'* Forwand Declaration problem with nested macros *
'************************************************* ***************

Stack Var Word[StackSize] ' This is the Stack
StackPTR Var Byte ' Pointer to Top of Stack
StackFull Var bit ' if=1, you cannot do another swGosub
StackEmpty var bit ' if=1, you cannot do a swReturn
SToverflow var bit ' swGosub called when Stack was Full
STunderflow var bit ' swReturn called when Stack was Empty
Address Var Word ' internal use only

StackEmpty = 1 ' Start with an Empty Stack

goto OverStack

'------------GetAddress Macro - Location insensitive -------------------------
ASM
GetAddress macro Label, Wout ; Returns the Address of a Label as a Word
CHK?RP Wout
movlw low Label
movwf Wout
movlw High Label
movwf Wout + 1
endm
ENDASM


'------------GOTO the address from a word variable.---------------------------
ASM
GotoAddress macro Win ; goto address specified by Win parameter
CHK?RP Win
movf Win + 1, W
movwf PCLATH ; Set PCH via PCLATH
movf Win, W
RST?RP
movwf PCL ; Writing to PCL will also load PCLath
endm ; into PCH
ENDASM


'------------Push Address onto the Stack--------------------------------------
Push:
if StackFull = 0 then ; If Stack isn't Full
Stack[StackPTR] = Address ; Add Address to the Stack
StackPTR = StackPTR + 1 ; Point to next Stack level
StackEmpty = 0 ; 0 - Since we just put something in it
else
SToverflow = 1 ; Stack was full, but you tried it again
endif
if StackPTR = StackSize then StackFull = 1 ; Update Full status
return

'------------Pop Address from the Stack---------------------------------------
Pop:
if StackPTR = 0 then StackEmpty = 1 ; Update Empty status
if StackEmpty = 0 then ; If Stack isn't Empty
Address = Stack[StackPTR-1] ; Get last Address from the Stack
StackPTR = StackPTR - 1 ; Point to Prior Stack level
StackFull = 0 ; 0 - Since we just removed 1
else
STunderflow = 1 ; Stack was Empty on swReturn
endif
if StackPTR = 0 then StackEmpty = 1 ; Update Empty status
return

'------------Gosub using Software Stack---------------------------------------
asm
swGosub macro Label
local ReturnPoint ; Local label
GetAddress ReturnPoint, _Address ; Get address of Return Point
L?CALL _Push ; Push Return Point on the Stack
GetAddress Label, _Address ; Get address of the Subroutine
GotoAddress _Address ; goto the Subroutine
ReturnPoint ; This is where swReturn will return to
endm
endasm

'------------Return using Software Stack---------------------------------------
Asm
swReturn macro
L?CALL _Pop ; Pop last Return Point from the Stack
GotoAddress _Address ; Goto the Return Point
endm
Endasm


OverStack:

()()()()()()()()()()()()()()()()()()()()()()()()() ()()()()()()()()()()()()()()()()()()()()()()()()

As you see there is a label without any thing. What happens when program jumps to this part especially after "goto OverStack"

There are some unknown instructions in asm parts for example:
CHK?RP
L?CALL

How can I interpret them?

2- The author has given an example of using this .inc file:

'************************************************* ***************
'* Name : Test_swStack.pbp *
'* Author : Darrel Taylor *
'* Date : 11/26/2003 *
'* Version : 1.0 *
'* Notes : Software Stack Demo (requires swStack.inc) *
'* : Tested with 16F877 on a LAB-X2 *
'* : View the output with HyperTerminal @ 9600 baud *
'************************************************* ***************
define LOADER_USED 1
define OSC 4
clear
' StackSize must be defined before include file
StackSize Con 20 ' Maximum StackSize is limited by the largest
' Word Array that you can fit in 1 bank
' Also, on an 18F type part the only limit is the
' Total amount of RAM (Big Stack)
include "swStack.inc" ' Include Software Stack routines

' SetUp Hardware USART
DEFINE HSER_TXSTA 24h ' Use this for Higher Baud Rates
DEFINE HSER_SPBRG 25 ' 9600 Baud at 4mhz
DEFINE HSER_CLROERR 1 ' Hser clear overflow automatically
CR Con 13 : LF Con 10 ' Carriage Return and Line Feed constants
hserout [27,"[2J"] ' Clear HyperTerminal screen

goto StartTest

'----- Simple swGosubs one after the other -----------------------------------
Sub1: ; Note how you can "nest" normal Gosubs within
Hserout ["Sub1 -"] ; a Software Gosub. Giving 4 additional levels.
gosub ShowStack ; Just "BE SURE" to match a GOSUB with a RETURN
@ swGosub _Sub2 ; and a swGosub with a swReturn
@ swReturn ;

Sub2:
Hserout ["Sub2 -"]
gosub ShowStack
@ swGosub _Sub3
@ swReturn

Sub3:
Hserout ["Sub3 -"]
gosub ShowStack
@ swReturn

StartTest:
Hserout ["--- Simple Test ---",cr,lf]
@ swGosub _Sub1 ; Software Gosub to Sub1, 2, 3
@ swGosub _Sub2 ; 2, 3
@ swGosub _Sub3 ; 3

'----- Recursive Test -------------------------------------------------------
TestLevel con StackSize
'TestLevel con StackSize + 1 ' uncomment to cause an OverFlow (not pretty)
Dir var bit

Hserout ["--- Recursive Test ---",cr,lf]
RecurseTest: ' swGosub's to itself until the Stack is Full
if StackFull = 1 then hserout ["Full -"] : gosub ShowStack
if Dir = 0 then
if StackPTR = TestLevel then
Dir = 1
else
hserout ["Enter-"] : gosub ShowStack
@ swGosub _RecurseTest ; The recursive GOSUB
hserout [" Exit-"] : gosub ShowStack
endif
EndIf
if Dir = 1 then
if StackEmpty = 1 then
Dir = 0
Hserout [cr,lf]
goto StartTest ' RecurseTest finished - Restart Simple test
else
@ swReturn ; Back out of Recursive Loop
endif
endif

Stop ' Should never make it here


'----- Display Stack Status --------------------------------------------------
ShowStack:
hserout ["StackPTR = ", dec StackPTR," Full=",dec StackFull," Empty=", _
dec StackEmpty," OFL=", dec SToverflow," UFL=",dec STunderflow,cr,lf]
pause 50
return

End

- Can anuone help me about knowing Hyperterminal?
- Can I display results on LCD instead of Hyperterminal? If yes HOW?

Thanks alot.

mister_e
- 13th December 2007, 13:56
As you see there is a label without any thing. What happens when program jumps to this part especially after "goto OverStack"

it just jump over the macro and subroutine, Don't forget, when you use INCLUDE, it basically just paste the whole code to yours, this is to avoid compilation error and some program weirdness like stack underflow with the first returns.



There are some unknown instructions in asm parts for example:
CHK?RP
L?CALL

How can I interpret them?
Both are PBP macro
CHK?RP x : is to PBP what BANKSEL is to asm, it check the BANK of x register/variable.
L?CALL label : basically not much than a GOSUB but at PBP assembler level.

Have a look at the following
http://www.picbasic.co.uk/forum/showpost.php?p=2009&postcount=3

None of the PBP macro are documented in a manual, just because it's not everybody that will use them anyways.

To output your data to a LCD, replace HSEROUT with LCDOUT.

HTH

yasser hassani
- 18th December 2007, 10:04
Thank you very much for your really graet and complete reply dear Mister_e. I understood many things from your helpful guide.
regards