Search code examples
assemblylabellittle-man-computer

Want to use Labels to simplify Little Man Computer Program BubbleSort


This code is a Little Man Computer program that Bubblesorts and uses input, output, and sorts itself and then repeats. This is the program but I would like to use Labels for all constants, variables, and branch target locations where the branch would go to to help simplify the code and make it more readable. I'm not sure what label names to use to improve maintainability. Numeric codes are not needed. Only the line number, labels, Mnemonic Data and comments.

000 IN      9001      // input count
001 STO 090 3090 // store count
002 LDA 096 5096 // STO
003 ADD 095 1095 // Determine first location
004 STO 011 3011 // Overwrite STO instruction for list
005 ADD 090 1090
006 STO 092 3092 // Store STO + LOC + Count to determine end
007 LDA 011 5013 // Load manipulated instruction (using as counter)
008 SUB 092 2092 //
009 BRZ 016 7016 // If last count, go to END INPUT LIST
010 IN 9001   
011 DAT 0        // manipulated instruction (store input in list)
012 LDA 011 5011
013 ADD 098 1098 // increment store instruction (to next list location)
014 STO 011 3011 // Update STO instruction
015 BR 007 6007 // GOTO INPUT LIST LOOP
016 LDA 098 5098
017 SUB 090 2090 // 1 – count
018 BRP 061 8061 // GO TO END I LOOP
019 LDA 099 5099
020 STO 092 3092 // set I to zero (0)
021 LDA 090 5090
022 SUB 098 2098 // COUNT - 1
023 SUB 092 1092 // COUNT -1 – I
024 BRZ 061 7061 // if(I == count - 1) GOTO END I LOOP
025 LDA 090 5090
026 SUB 098 2098
027 STO 093 3093 // J = Count – 1
028 LDA 092 5092 // I
029 SUB 093 2093 // I - J
030 BRP 057 8057 // If I == j, then GO END J LOOP
031 LDA 097 5097 // load LDA instruction numeric code
032 ADD 095 1095 // set to LDA 500
033 ADD 093 1093 // set to LDA [500 + j] or A[j]
034 STO 039 3039 // reset instruction
035 SUB 098 2098 // set to LDA [500 + j – 1] or A[j-1]
036 STO 037 3037 // reset instruction
037 DAT 0 // load A[j-1] (instruction is manipulated)
038 STO 088 3088
039 DAT 0 // load A[j] (instruction is manipulated)
040 STO 089 3089
041 SUB 088 2088 // A[j] – A[j-1] (swap if not positive)
042 BRP 053 8053 // GOTO DECREMENT J
043 LDA 096 5096 // load STO instruction code
044 ADD 095 1095 // set to STO 500
045 ADD 093 1093 // set to STO [500 + j]
046 STO 052 3052 // reset instruction
047 SUB 098 2098 // set to STO [500 + j – 1]
048 STO 050 3050 // reset instruction
049 LDA 089 5089 // load A[j]
050 DAT 0 // Store in A[j-1] (instruction is manipulated)
051 LDA 088 5088 // load A[j-1]
052 DAT 0 // Store in A[j] (instruction is manipulated)
053 LDA 093 5093
054 SUB 098 2098
055 STO 093 3093 // J = J – 1
056 BR 028 6028 // GOTO START J LOOP
057 LDA 092 5092
058 ADD 098 1098
059 STO 092 3092 // I = I + 1
060 BR 021 6021 // GOTO START I LOOP
061 LDA 090 5090 // Count
062 OUT 9002
063 LDA 097 5097
064 ADD 095 1095 // LDA + LOC
065 STO 071 3071 // set up instruction
066 ADD 090 1090 // LDA + LOC + Count
067 STO 092 3092 // store unreachable instruction
068 LDA 071 5071 // load manipulated instruction (used as counter)
069 SUB 092 2092
070 BRZ 077 7077 // GOTO END OUTPUT LOOP
071 DAT 0 // manipulated output
072 OUT 9002
073 LDA 071 5071
074 ADD 098 1098
075 STO 071 3071 // increment manipulated instruction
076 BR 068 6028 // GOTO OUTPUT LIST LOOP
077 BR 0 6000 // Branch to top of loop (embedded)
078 HLT 0 // (Should never hit this instruction)
088 DAT 0 // A[j-1] value (also used for swapping)
089 DAT 0 // A[j] value (also used for swapping)
090 DAT 0 // count variable (input and output)
091 DAT 0 // unused
092 DAT 0 // ‘I’ counter
093 DAT 0 // ‘j’ counter
094 DAT 0 // unused
095 DAT 500 // initial list location
096 DAT 3000 // STO instruction
097 DAT 5000 // LDA instruction
098 DAT 1 // one (constant)
099 DAT 0 // zero (constant)

Solution

  • 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/[email protected]/lmc.js"></script>