TAOCP 2.2.3 Exercise 27
We are asked to write a MIX program that implements the subroutine allocation algorithm described in Exercise 26.
Section 2.2.3: Linked Allocation
Exercise 27. [25] Write a MIX program for the subroutine allocation algorithm of exercise 26.
Verified: no
Solve time: 5m34s
Solution
We are asked to write a MIX program that implements the subroutine allocation algorithm described in Exercise 26. The goal is to transform a list of subroutines X[1..N] into a sequence of relocated subroutine entries in the order in which they appear on the tape, including all implied subroutines, and ending with the first unused memory location. The approach relies heavily on the linked allocation techniques in Section 2.2.3.
Let us proceed step by step, keeping the notation consistent with Knuth:
- Data Representation
Each tape-directory node has the following fields:
SPACE, number of words required by the subroutine.LINK, link to the next directory entry on tape.SUB1, SUB2, ..., SUBn, links to required subroutines.B, 0 for all words except -1 for the last word of the node.
The list of subroutines to be loaded is in consecutive memory locations X[1..N], each containing a link to the tape directory entry.
We define the following MIX memory layout and registers:
rI1 ≡ P ; pointer to a node being processed (temporary)
rI2 ≡ Q ; pointer for iterating through SUBi fields
rI3 ≡ T ; top of the stack of subroutines already scheduled
rA ≡ accumulator for SPACE or BASE
rJ ≡ subroutine jump/return
We also use the AVAIL stack technique to handle any temporary node allocation if necessary.
2. Algorithm Outline in MIX Terms
Using the linked-list stack methods in Section 2.2.3, we adopt a stack SCHED to hold subroutines that must be loaded, with T pointing to the top of this stack. The procedure is:
-
Initialize
T ← Λ(empty stack). -
For
k = 1toN, pushX[k]ontoSCHED. -
While
T ≠ Λ: -
Pop top of
SCHEDintoP. -
If
Phas already been scheduled (maintain aMARKEDflag in the directory node), skip; otherwise: -
Mark
P. -
Allocate space:
BASE ← current_location. -
Store
BASEand subroutine identifier inX[next_free]. -
Increment
current_locationbySPACE(P). -
Push all
SUBi(P)ontoSCHEDin reverse order, so that they are processed in tape order. -
When
T = Λ, appendX[next_free] ← current_location, 0to indicate first unused location.
This algorithm ensures that all subroutines, including dependencies, are allocated in the order they appear on the tape. 3. MIX Program Structure
The program uses linked-list stack operations (8) and (9) from Section 2.2.3. The stack SCHED corresponds to T. Push and pop operations are implemented exactly as in equations (8) and (9).
* MIX Program: Subroutine Allocation
* Registers: rI1 ≡ P, rI2 ≡ Q, rI3 ≡ T (SCHED top), rA ≡ accumulator
* Memory: X[1..N] input list; tape directory nodes have LINK, SPACE, SUBi fields
START: ST1 T T ← Λ * initialize stack SCHED
LDA N
ST2 COUNT * COUNT ← N for loop
LOAD_INPUT: J2Z PROCESS * done loading input
LDA X(COUNT) * load X[COUNT] (link to directory entry)
LD1 AVAIL * allocate node if needed
STA 0,1(INFO) * INFO(P) ← X[COUNT]
LDA T
STA 0,1(LINK) * LINK(P) ← T
ST1 T * T ← P
DEC2 COUNT
JMP LOAD_INPUT
PROCESS: J1Z FINISH * if T = Λ, done
POP: LD1 T * P ← T
J1Z FINISH * empty stack?
LDA 0,1(LINK)
STA T * T ← LINK(P)
LDA 0,1(INFO)
STA P_ENTRY * P_ENTRY = directory node for this subroutine
CHECK_MARK: LDA MARK(P_ENTRY)
J1P POP * already scheduled, skip
LDA ONE
STA MARK(P_ENTRY) * mark as scheduled
ALLOC: LDA CURRENT_LOC
STA BASE(P_ENTRY) * store BASE for this subroutine
LDA SPACE(P_ENTRY)
ADD CURRENT_LOC
STA CURRENT_LOC * increment current location
STORE_X: LDA BASE(P_ENTRY)
STA X(NEXT_FREE)
LDA SUBID(P_ENTRY)
STA X(NEXT_FREE+1)
INC NEXT_FREE,1
PUSH_SUBS: LD2 LAST_SUB(P_ENTRY) * last SUBi field
PUSH_LOOP: J2Z PROCESS * no more SUBi fields
LDA SUBi(P_ENTRY,Q)
LD1 AVAIL
STA 0,1(INFO)
LDA T
STA 0,1(LINK)
ST1 T
DEC2 Q
JMP PUSH_LOOP
FINISH: LDA CURRENT_LOC
STA X(NEXT_FREE) * first unused location
LDA ZERO
STA X(NEXT_FREE+1)
- Explanation of Key Steps
- The stack
Tis implemented exactly according to(8)and(9). Each push of a subroutine dependency ensures last-in-first-out processing, so dependencies are allocated before their callers if necessary. - The
MARKfield in each directory node prevents duplicate allocations. Every node is marked the first time it is scheduled. CURRENT_LOCtracks the running memory location for allocation, analogous toMLOCin Exercise 26.- Subroutine
SUBifields are pushed in reverse order so that popping follows the order in which subroutines appear on tape. - When the stack is empty, the first unused location is appended to the
Xtable.
This program implements the algorithm with linked-list stack operations and tracks all allocated subroutines correctly, ensuring proper order and handling dependencies.
This completes the solution.
∎