Just use the comments as inspiration for the labels. Lines that are not the target of any operation can go without labels. So for instance:
start IN // input count
STO count // store count
LDA stoInstruction // STO
ADD location // Determine first location
STO storeInput // Overwrite STO instruction for list
ADD count
STO i // Store STO + LOC + Count to determine end
loopInput LDA storeInput // Load manipulated instruction (using as counter)
SUB i //
BRZ exitInputLoop // If last count, go to END INPUT LIST
IN
storeInput DAT // manipulated instruction (store input in list)
LDA storeInput
ADD one // increment store instruction (to next list location)
STO storeInput // Update STO instruction
BR loopInput // GOTO INPUT LIST LOOP
exitInputLoop LDA one
SUB count // 1 – count
BRP exitLoopI // GO TO END I LOOP
LDA zero
STO i // set I to zero (0)
loopI LDA count
SUB one // COUNT - 1
SUB i // COUNT -1 – I
BRZ exitLoopI // if(I == count - 1) GOTO END I LOOP
LDA count
SUB one
STO j // J = Count – 1
loopJ LDA i // I
SUB j // I - J
BRP exitLoopJ // If I == j, then GO END J LOOP
LDA ldaInstruction // load LDA instruction numeric code
ADD location // set to LDA 500
ADD j // set to LDA [500 + j] or A[j]
STO loadCurrent // reset instruction
SUB one // set to LDA [500 + j – 1] or A[j-1]
STO loadPrevious // reset instruction
loadPrevious DAT // load A[j-1] (instruction is manipulated)
STO previous
loadCurrent DAT // load A[j] (instruction is manipulated)
STO current
SUB previous // A[j] – A[j-1] (swap if not positive)
BRP decrementJ // GOTO DECREMENT J
LDA stoInstruction // load STO instruction code
ADD location // set to STO 500
ADD j // set to STO [500 + j]
STO storeCurrent // reset instruction
SUB one // set to STO [500 + j – 1]
STO storePrevious // reset instruction
LDA current // load A[j]
storePrevious DAT // Store in A[j-1] (instruction is manipulated)
LDA previous // load A[j-1]
storeCurrent DAT // Store in A[j] (instruction is manipulated)
decrementJ LDA j
SUB one
STO j // J = J – 1
BR loopJ // GOTO START J LOOP
exitLoopJ LDA i
ADD one
STO i // I = I + 1
BR loopI // GOTO START I LOOP
exitLoopI LDA count // Count
OUT
LDA ldaInstruction
ADD location // LDA + LOC
STO instruction // set up instruction
ADD count // LDA + LOC + Count
STO i // store unreachable instruction
loopOutput LDA instruction // load manipulated instruction (used as counter)
SUB i
BRZ exitLoopOutput // GOTO END OUTPUT LOOP
instruction DAT // manipulated output
OUT
LDA instruction
ADD one
STO instruction // increment manipulated instruction
BR loopOutput // GOTO OUTPUT LIST LOOP
exitLoopOutput BR start // Branch to top of loop (embedded)
HLT // (Should never hit this instruction)
previous DAT // A[j-1] value (also used for swapping)
current DAT // A[j] value (also used for swapping)
count DAT // count variable (input and output)
DAT // unused
i DAT // ‘I’ counter
j DAT // ‘j’ counter
DAT // unused
location DAT 500 // initial list location
stoInstruction DAT 3000 // STO instruction
ldaInstruction DAT 5000 // LDA instruction
one DAT 1 // one (constant)
zero DAT 0 // zero (constant)
Notes:
This LMC is a variant on the original LMC, which had 3-digit numbers, while you seem to be working with one that uses 4-digit numbers.
The code is not very concise: it uses 98 mailboxes, excluding the storage needed for the input data. It can be done with fewer. Look for instance at this implementation which uses 75 mailboxes.
You write that line numbers are needed, but when you use labels, line numbers (i.e. mailbox numbers) become irrelevant: the LMC-assembler can assign them during assembly.
Running on a standard, 100-mailbox LMC
After your comments, I provide here a version of your code that is adapted to the standard LMC. This means that there is not much space left for the actual input data: just 11 mailboxes are left over for the data.
I had to replace the following part:
location DAT 500 // initial list location
stoInstruction DAT 3000 // STO instruction
ldaInstruction DAT 5000 // LDA instruction
...with this:
location DAT list // initial list location
stoInstruction DAT 300 // STO instruction
ldaInstruction DAT 500 // LDA instruction
list DAT // start of the list
This is necessary as in the standard LMC:
- the opcodes are 3 digits, not 4 digits;
- mailbox addresses are 2 digits, not 3 (so 500 is unacceptable);
- it is better to just use the next available address for the location of the list, instead of a hardcoded mailbox address.
I also removed the two lines which define unused mailboxes.
Finally, I would change the two BRZ
instructions with BRP
instructions, as there is in theory no guarantee what the accumulator's value is when the previous SUB
gave a negative result. In that case the accumulator's value cannot be relied upon (as it can only have non-negative values -- see Wikipedia). So performing a BRZ
on an undefined value is taking a risk. BRP
is a safe instruction, as it checks the flag -- not the accumulator.
#input: 3 44 22 99
start IN // input count
STO count // store count
LDA stoInstruction // STO
ADD location // Determine first location
STO storeInput // Overwrite STO instruction for list
ADD count
STO i // Store STO + LOC + Count to determine end
loopInput LDA storeInput // Load manipulated instruction (using as counter)
SUB i //
BRP exitInputLoop // If last count, go to END INPUT LIST
IN
storeInput DAT // manipulated instruction (store input in list)
LDA storeInput
ADD one // increment store instruction (to next list location)
STO storeInput // Update STO instruction
BR loopInput // GOTO INPUT LIST LOOP
exitInputLoop LDA one
SUB count // 1 – count
BRP exitLoopI // GO TO END I LOOP
LDA zero
STO i // set I to zero (0)
loopI LDA count
SUB one // COUNT - 1
SUB i // COUNT -1 – I
BRZ exitLoopI // if(I == count - 1) GOTO END I LOOP
LDA count
SUB one
STO j // J = Count – 1
loopJ LDA i // I
SUB j // I - J
BRP exitLoopJ // If I == j, then GO END J LOOP
LDA ldaInstruction // load LDA instruction numeric code
ADD location // set to LDA 500
ADD j // set to LDA [500 + j] or A[j]
STO loadCurrent // reset instruction
SUB one // set to LDA [500 + j – 1] or A[j-1]
STO loadPrevious // reset instruction
loadPrevious DAT // load A[j-1] (instruction is manipulated)
STO previous
loadCurrent DAT // load A[j] (instruction is manipulated)
STO current
SUB previous // A[j] – A[j-1] (swap if not positive)
BRP decrementJ // GOTO DECREMENT J
LDA stoInstruction // load STO instruction code
ADD location // set to STO 500
ADD j // set to STO [500 + j]
STO storeCurrent // reset instruction
SUB one // set to STO [500 + j – 1]
STO storePrevious // reset instruction
LDA current // load A[j]
storePrevious DAT // Store in A[j-1] (instruction is manipulated)
LDA previous // load A[j-1]
storeCurrent DAT // Store in A[j] (instruction is manipulated)
decrementJ LDA j
SUB one
STO j // J = J – 1
BR loopJ // GOTO START J LOOP
exitLoopJ LDA i
ADD one
STO i // I = I + 1
BR loopI // GOTO START I LOOP
exitLoopI LDA count // Count
OUT
LDA ldaInstruction
ADD location // LDA + LOC
STO instruction // set up instruction
ADD count // LDA + LOC + Count
STO i // store unreachable instruction
loopOutput LDA instruction // load manipulated instruction (used as counter)
SUB i
BRP exitLoopOutput // GOTO END OUTPUT LOOP
instruction DAT // manipulated output
OUT
LDA instruction
ADD one
STO instruction // increment manipulated instruction
BR loopOutput // GOTO OUTPUT LIST LOOP
exitLoopOutput BR start // Branch to top of loop (embedded)
HLT // (Should never hit this instruction)
previous DAT // A[j-1] value (also used for swapping)
current DAT // A[j] value (also used for swapping)
count DAT // count variable (input and output)
i DAT // ‘I’ counter
j DAT // ‘j’ counter
location DAT list // initial list location
stoInstruction DAT 300 // STO instruction
ldaInstruction DAT 500 // LDA instruction
one DAT 1 // one (constant)
zero DAT 0 // zero (constant)
list DAT
<script src="https://cdn.jsdelivr.net/gh/trincot/lmc@v0.815/lmc.js"></script>