TAOCP 5 Exercise 8

We are given two MIX words in locations `A` and `B`.

Section 5: Introduction to Sorting

Exercise 8. ▶ [30] Locations A and B contain two numbers $a$ and $b$, respectively. Show that it is possible to write a MIX program that computes and stores $\min(a, b)$ in location C, without using any jump operators. (Caution: Since you will not be able to test whether or not arithmetic overflow has occurred, it is wise to guarantee that overflow is impossible regardless of the values of $a$ and $b$.)

Verified: yes
Solve time: 1h07m


Solution

We are given two MIX words in locations A and B. Each word consists of a sign (±) and a five‑byte magnitude (bytes 1-5, each 0-63). The task is to place min(a,b) into location C using a straight‑line MIX program - no jump instructions of any kind - and without risking arithmetic overflow for any possible values of a and b.

1. Overall strategy

The comparison a > b can be decided by examining the signs and, when the signs agree, the magnitudes. Because magnitudes are non‑negative, subtracting them never overflows. We therefore:

  1. Extract the sign of each operand as a word of magnitude 1 carrying that sign (+1 or ‑1).
  2. Extract the magnitudes (always positive).
  3. Compute d = |a| − |b| (safe) and extract its sign as a magnitude‑1 word s_d.
  4. Form the word
    [ V = T - S \cdot (1 + s_d), ] where S, T, s_d are the magnitude‑1 words for the signs of a, b, d.
    The sign of V is positive exactly when a < b; it is negative when a > b (for a = b either sign may occur, which is harmless because both choices give the correct minimum).
  5. Convert the sign of V into a numeric flag F that is 0 if V > 0 (choose a) and 1 if V < 0 (choose b). This is done by
    • obtaining SGN = sign(V)·1 (magnitude 1, sign of V),
    • computing 1 - SGN, which yields 0 (if SGN = +1) or 2 (if SGN = -1),
    • dividing by 2 (using DIV, perfectly safe because the dividend is at most 2).
  6. Finally compute
    [ \min(a,b) = a \cdot (1-F) + b \cdot F . ] Multiplication by 0 or 1 is performed with MUL; the 10‑byte product resides in registers A and X. Because the multiplier is 0 or 1, the high part (A) is always zero and the low part (X) contains exactly the chosen operand (or +0). Storing X and adding the two stored values yields the desired minimum. Adding +0 never overflows.

All arithmetic operations are on quantities whose magnitudes are bounded by 3 or by the original magnitudes, so overflow is impossible.

2. Sign extraction

In MIX the sign is a separate flip‑flop; it is not a byte and is not affected by circular shifts. To obtain a word of magnitude 1 with the sign of a given value x:

LDA  x
SRA  5          * magnitude becomes 0, sign unchanged (+0 or -0)
OR   ONE        * magnitude becomes 1, sign unchanged -> +1 or -1

Here ONE is a constant word with magnitude 1 and positive sign.

3. Magnitude comparison

The magnitudes are non‑negative, so their difference fits in one word without overflow:

LDA  A(1:5)     * load |a| (positive)
STA  MAG_A
LDA  B(1:5)
STA  MAG_B
LDA  MAG_A
SUB  MAG_B      * d = |a| - |b|
STA  DIFF

The sign of d is extracted exactly as in step 2, yielding s_d = ±1 (magnitude 1).

4. Computing V

Let S, T, s_d be the magnitude‑1 words for the signs of a, b, d. We compute

[ V = T - S \cdot (1 + s_d). ]

1 + s_d is either 0 (if s_d = -1) or 2 (if s_d = +1); both are positive and at most 2. The product S·(1+s_d) therefore has magnitude 0 or 2 and the sign of S. Subtracting from T (magnitude 1) gives V with magnitude 1 or 3 and a sign that tells us whether a < b (positive) or a > b (negative). The computation uses only ADD, SUB, MUL:

LDA  ONE
ADD  SIGN_DIFF     * 1 + s_d
STA  TEMP1
LDA  SIGN_A
MUL  TEMP1         * product in A and X; magnitude ≤ 2 -> A=0, X=product
STX  PROD
LDA  SIGN_B
SUB  PROD
STA  V

5. Converting the sign of V to a 0/1 flag F

LDA  V
SRA  5
OR   ONE           * SGN = sign(V)·1  (+1 or -1)
STA  SGN
LDA  ONE
SUB  SGN           * 1 - SGN = 0 (if SGN=+1) or 2 (if SGN=-1), always positive
LDX  ZERO          * clear X for division
DIV  TWO           * quotient = 0 or 1 in A
STA  F

TWO is the constant +2. The division is exact and cannot overflow because the dividend is at most 2.

6. Selecting the minimum

LDA  ONE
SUB  F
STA  ONE_MINUS_F   * 1-F (0 or 1, positive)

LDA  A
MUL  ONE_MINUS_F   * X = a*(1-F)  (a or +0)
STX  TEMP1

LDA  B
MUL  F             * X = b*F      (b or +0)
STX  TEMP2

LDA  TEMP1
ADD  TEMP2         * one term is the chosen operand, the other is +0
STA  C

MUL by 0 or 1 produces a 10‑byte product whose high part (A) is zero and whose low part (X) is exactly the multiplicand (with its sign) or +0. STX stores that full word. Adding +0 to a word never changes it and never overflows.

7. Complete MIX program

* MINIMUM OF A AND B WITHOUT JUMPS
        LDA     A
        SRA     5
        OR      ONE
        STA     SIGN_A
        LDA     B
        SRA     5
        OR      ONE
        STA     SIGN_B
        LDA     A(1:5)
        STA     MAG_A
        LDA     B(1:5)
        STA     MAG_B
        LDA     MAG_A
        SUB     MAG_B
        STA     DIFF
        LDA     DIFF
        SRA     5
        OR      ONE
        STA     SIGN_DIFF
        LDA     ONE
        ADD     SIGN_DIFF
        STA     TEMP1
        LDA     SIGN_A
        MUL     TEMP1
        STX     PROD
        LDA     SIGN_B
        SUB     PROD
        STA     V
        LDA     V
        SRA     5
        OR      ONE
        STA     SGN
        LDA     ONE
        SUB     SGN
        LDX     ZERO
        DIV     TWO
        STA     F
        LDA     ONE
        SUB     F
        STA     ONE_MINUS_F
        LDA     A
        MUL     ONE_MINUS_F
        STX     TEMP1
        LDA     B
        MUL     F
        STX     TEMP2
        LDA     TEMP1
        ADD     TEMP2
        STA     C
        HLT
ONE     CON     1
TWO     CON     2
ZERO    CON     0
SIGN_A  DS      1
SIGN_B  DS      1
MAG_A   DS      1
MAG_B   DS      1
DIFF    DS      1
SIGN_DIFF DS    1
TEMP1   DS      1
PROD    DS      1
V       DS      1
SGN     DS      1
F       DS      1
ONE_MINUS_F DS  1
TEMP2   DS      1

8. Verification

  1. Sign extraction - SRA 5 clears the magnitude, leaving +0 or ‑0. OR ONE sets the least‑significant byte to 1 while preserving the sign, yielding +1 or ‑1. This correctly converts the sign to a numeric magnitude‑1 word.

  2. Magnitude difference - MAG_A and MAG_B are non‑negative; their difference is in [-MAX, MAX], so no overflow occurs.

  3. Computation of V - 1 + s_d is 0 or 2; S·(1+s_d) has magnitude 0 or 2 and sign of S. T has magnitude 1. The subtraction T - S·(1+s_d) therefore produces a word of magnitude 1 or 3. The truth table for the sign of V matches a < b (positive) vs. a > b (negative); equality may produce either sign, which is acceptable.

  4. Flag F - SGN = sign(V)·1 is +1 or ‑1. 1 - SGN gives 0 or 2. Division by 2 yields 0 or 1 exactly. DIV is safe because the dividend ≤ 2.

  5. Final selection - MUL by 0 or 1 places the chosen operand (or +0) in X; STX stores it. Adding the two stored words gives the chosen operand because the other is +0. No arithmetic operation can overflow: all ADD/SUB involve numbers of magnitude at most 3 or one operand is +0; MUL never sets overflow; DIV’s quotient is at most 1.

  6. No jumps - The program uses only LDA, STA, SRA, OR, SUB, ADD, MUL, STX, LDX, DIV, HLT, and pseudo‑ops. No jump instruction appears.

Thus the program correctly computes min(a,b) in location C for all MIX words a, b, without jumps and without any possibility of arithmetic overflow. ∎