|
Writing Recursive
Routines
-
Recursive subroutines
are routines that are able to call themselves from somewhere within
themselves. For some reason, people, generally programming
students, find the concept difficult - especially in assembler
language.
-
In actuality, the
concept and coding technique is quite simple.
-
Recursive subroutines
are useful in designing parsers, compilers, translators, interpreters
and complex mathematical functions.
-
There are only a few
simple considerations to designing recursive routines. The
routine must be fully re-entrant and it must have a standard way of
exiting to the caller (itself or a higher level caller).
-
From force of habit, I
always code a linkage stack for use in any subroutine I write.
This is the first step in designing a recursive subroutine.
-
For simple routines,
you may allocate a static stack from real memory, but for more complex
routines, it might be necessary to allocate a dynamic stack that can
grow or shrink as required. I'll typically design a dynamic
linkage stack using a linked list.
-
One of the most
important considerations is to prevent stack overflow (i.e.,
exceeding the capacity of the stack).
-
Another of the most
important considerations is to code an exit from the recursion.
Failure to do this properly will end up in an endless loop and stack
overflow or storage allocation failure in the case of a dynamic stack.
-
The following is a
code "snippet" for a simple recursive subroutine without
stack checking or a dynamic stack:
RECURSE CSECT
CSECT Definition.
RECURSE AMODE
31
31-Bit Addressing.
RECURSE RMODE
ANY
Any Residency.
ENTRY RECEP
Entry point.
.
.
.
RECEP DS
0H
CSECT Entry.
.
.
Allocate save area storage...
.
...for re-entrancy.
.
STORAGE
OBTAIN,
Allocate storage for
stack. C
LENGTH=STACKL, Size of storage to
allocate. C
LOC=ANY,
Any (31/24 Bit) storage location. C
COND=YES
We'll handle any exceptions.
LTR
R15,R15
Successfull allocation?
BNZ
FAIL
Take branch if not.
LR
R8,R1
Load A(Allocated storage).
.
.
.
L R15,=A(RERTN)
Load A(Recursive Routine).
BALR
R14,R15
Call Recursive Routine first time.
.
.
.
STORAGE
RELEASE,
De-allocate stack
storage. C
LENGTH=STACKL, Size of storage to
de-allocate. C
ADDR=(R8)
Address of storage to de-allocate.
.
.
.
L
R14,RSAR14
Some return address save area.
.
.
Free any other allocated storage.
.
XR
R15,R15
Clear return code.
BR
R14
Return to caller.
EJECT
*--------------------------------------------------------------------*
* RERTN - Recursive
Subroutine.
*
*--------------------------------------------------------------------*
SPACE ,
RERTN DS
0H
Recursive routine entry point.
ST
R14,0(,R8)
Store return address to stack.
LA
R8,4(,R8)
Increment stack pointer.
.
.
.
BNE
RERTN10
Some condition to start recursion.
OI
GETOUT,X'80' Set the
"get out" switch.
RERTN10 DS
0H
Recursion begins.
.
.
.
TM
GETOUT,X'80' Some kind of
"get out" switch.
BO
RERTN99
Exit this recursion.
BAL
R14,RERTN
Call ourself.
RERTN99 DS
0H
Routine exit.
SH
R8,=H'4'
Decrement stack pointer.
L
R14,0(,R8)
Restore return address.
BR
R14
Return to caller.
SPACE ,
*--------------------------------------------------------------------*
EJECT
.
.
.
END ,
End of module.
|
I will continue to add
tips and techniques as time permits.
Please direct any
inquiries or problems regarding this web to webmaster@marcsweb.com
Page design, composition and HTML by Marc Niegowski
Copyright © 1998-2012, Marc Niegowski - Connectivity, Inc., All Rights Reserved
23 W. Fourth Street • Media • Pennsylvania • 19063-2805 • USA
Phone: 610-566-0227 • Fax: 610-566-0641 • Email: Marc@Tech-Center.com
Revision Date:
Wednesday, November 15, 2006 10:03:31 AM
|