The LOOPS and SUBROUTINES are two of the most important
constructs which are at the heart of all programming paradigms.
The IBM's BAL (360) provides support for creating efficient
LOOPS and SUBROUTINE calls with help of a rich inventory of the
instructions at hand.
The effect of executing either of these is shown in following pseudocode:
The type 2 loops are created using either of following:
Both of these are examples of type RS instructions that are coded as follows.
Whenever either of these are present, following are assigned:
Once these three are identified, working of both these instructions can be understood below:
The Steps 1,2 can be implemented using either of following instructions:
The
Here we show a pseudocode to demonstrate the call to an internal subroutine:
Its time to finish the current post here, please take time to post your comments or suggestions below. If you have any example code, feel free to share that as well.
CREATING LOOP STRUCTURES
The LOOPS are essentially the chunks of code which are executed repeatedly subject to certain control condition. Two types of looping structures are most frequently encountered:- Type1: Loop with known number of cycles
- Type2: Loop with unknown number of cycles
BCT r1,D(X,B)
BCTR r1,r2
|
The effect of executing either of these is shown in following pseudocode:
BCT:
|r1| = |r1|-1
if(|r1|!=0) take branch to D(X,B)
else go to next instruction
1. Condition code remains unaltered.
BCTR:
|r1| = |r1|-1
if((|r1|!=0)&&(|r2|!=R0)) take branch to |r2|
else go to next instruction.
1. Condition code remains unaltered.
|
The type 2 loops are created using either of following:
BXLE r1,r2,D(B)
BXH r1,r2,D(B)
1. Note the absence of X in address.
|
Both of these are examples of type RS instructions that are coded as follows.
h_{0}h_{0}h_{r1}h_{r2}h_{b}h_{D}h_{D}h_{D}
Where:
h_{0}h_{0} : Machine code of the instruction
h_{r1}: Register r1
h_{r2}: Register r2
h_{B} : Base Register
h_{D} : 3 Byte displacement
|
Whenever either of these are present, following are assigned:
- Index Register (INDR)
- Increment Register (INCR)
- Limit Register (LIMR)
INDR = r1
if (r2 == Even Numbered) :
INCR = r2
LIMR = r2+1
else if (r2 == Odd Numbered):
INCR = r2
LIMR = r2
|
Once these three are identified, working of both these instructions can be understood below:
BXLE:
|INDR| = |INDR|+|INCR|
if (|INDR| <= |LIMR|) take a branch to D(B)
else go to next instruction
1. Condition code remains unaltered.
BXH:
|INDR| = |INDR|+|INCR|
if (|INDR| > |LIMR|) take a branch to D(B)
else go to next instruction
1. Condition code remains unaltered.
|
CREATING INTERNAL SUBROUTINES
Succession of logical steps for calling a subroutine is summarised below:
1. Store the address of next instruction in some register. 2. Take a branch to the address where subroutine begins. 3. Once there, store all the registers to an area in memmory 4. Perform the tasks coded into the subroutine 5. At the end, restore all registers from area in Step:3 6. Take a branch to main program using information stored in Step:1 |
The Steps 1,2 can be implemented using either of following instructions:
BAL r,D(X,B)
BALR r1,r2
Pseudocode:
BAL:
|r| = |PSW (right 32 bits)|
take a branch to D(X,B)
BALR:
|r1| = |PSW (right 32 bits)|
if (r2 != R0) take a branch to |r2|
else go to next instruction
|
The
BAL instruction cause right 32 bits of PSW which contain
the address of next instruction, to be stored in 'r' register. Then a
branch is taken to the address D(X,B), which in current context is the
address of subroutine we wish to call. The BALR instruction
is similar to BAL, except that the branching takes place
into the address contained in r2 and that if r2
is R0, branching does not take place.
Upon being called, a subroutine needs to store caller's data before using any of the registers, so that they may be restored upon exit. This constitute steps 3 and 5, and may be implemented with following instructions:
STM r1,r2,D(B) :STORE TO MEMMORY
LM r1,r2,D(B) :LOAD FROM MEMMORY
Pseudocode:
STM:
Store registers r1 through r2 into 1 FW each
of the contiguous memmory starting D(B).
LM :
Restore registers r1 through r2 from contiguous
memmory starting at D(B), reading 1 FW into each.
*NOTE: Note address is coded as D(B): X not allowed !!
|
Here we show a pseudocode to demonstrate the call to an internal subroutine:
***********************************************************
*MAIN FUNCTION: CALLER DEMO *
*R6: CONTAINS ADDRESS OF NEXT TO CALLER *
***********************************************************
MAIN CSECT :CONTROL SECT
USING MAIN,15 :ESTABLISH BASE REG
BAL R6,SUBR :STORE NEXT INSTR,
* AND BRANCH TO A(SUBR)
BR R14 :EXIT
***********************************************************
*SUBROUTINE SUBR: DEMO SKELETON *
*R6: CONTAINS ADDRESS OF NEXT TO CALLER *
***********************************************************
SUBR STM R0,R15,SUBSAFE :STORE REGS INTO MEMMORY
... .............. :DO STUFF
... .............. :DO STUFF
LM R0,R15,SUBSAFE :RESTORE REFS FROM MEMMORY
BR R6 :BRANCH BACK TO CALLER
LTORG :LITERALS STORAGE
SUBSAFE DS 18F :RESERVE REG STORAGE
END MAIN :END MAIN
|
Its time to finish the current post here, please take time to post your comments or suggestions below. If you have any example code, feel free to share that as well.