1
\$\begingroup\$

I'm using an LC3 microarchitecture simulator to write assembly code. I've only been writing assembly for about three weeks, so I am still very new.

My goal is to print all the numbers leading up to a set value, so for example, if the user selects '6' the console prints 012345. My code works, but the unit test says my code is inefficient or has an infinite loop.

I set the value by manually setting R1 in my simulator to any value. The rest is automated with the code, starting at 0x3000.

LD, R0, X3001 ;Load R0 with 0
0 ;I did this b/c I don't know how to load a register with ascii values
AND R2, R2, #0 ; Set R2=0
NOT R3, R1 ;invert R1, store in R3
ADD R3, R3, #1 ;Add 1 to R3, now R3=-R1
ADD R4, R0, R3 ; better way to perform loop? added these to maintain loop
BRz X300b ; if previous math ever produces 0, skip to halt
OUT ; print single char
ADD R0, R0, #1 ; R0++
ADD R1, R1 #-1 ; R1--
BRnzp X3006 ;Always branch back to the above BR instruction
HALT 

Hex:

3000
2000
0030
54a0
967f
16e1
1803
0404
f021
1021
127f
0ffb
f025

So my question is, is there any way to make this more efficient?

\$\endgroup\$
1
\$\begingroup\$

Points about your program.

  • The 2 instructions at the top don't match the 3 dumped values! There are 12 lines of source but there are 13 values in the dump. .ORIG X3000 is not an instruction. It's rather a directive and you should not find any value from it in the dump.

  • Why don't you place the data below the HLT instruction? A much safer place than within the instructions that get executed. Your trick works because of how the BR instruction is encoded.

  • On an architecture with limited registers available, it's best to try to use as few as possible to get the work done. Your code uses 5 registers where you can easily do it with 2 registers.

  • You don't need to use the extra register R4 to find out if the input was 0. AND-ing R1 to itself will not destroy it and will set the flags for inspecting:

    AND R1, R1, R1
    BRz X300B      ;Skip if input was 0
    
  • It's inefficient to branch always to just another branch instruction. See how I solved the same branching.


An improved version.

My goal is to print all the numbers leading up to a set value

Let's presume the user selects a value from 0 to 9.

For now you've manually set the user's value in R1. You can use it as a (down)counter. You stop the program as soon as a negative value appears.

.ORIG X3000
LEA   R0, X3030     ;Loads "0" in R0[7:0]
BRnzp X3004         ;Go test for 0 input
OUT                 ;Display R0[7:0]
ADD   R0, R0, #1    ;R0++
ADD   R1, R1, #-1   ;R1--
BRzp  X3002         ;Continue with zero or positive
HLT                 ;Stop (R1 = #-1)

OUT only depends on bits [7:0]. The high bits loaded with LEA don't matter.
If you don't like this trick, then go with the usual way of loading a constant from memory:

.ORIG X3000
LD    R0, X3007     ;Loads "0" in R0
BRnzp X3004         ;Go test for 0 input
OUT                 ;Display R0[7:0]
ADD   R0, R0, #1    ;R0++
ADD   R1, R1, #-1   ;R1--
BRzp  X3002         ;Continue with zero or positive
HLT                 ;Stop (R1 = #-1)
.FILL X0030         ;Character "0"
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.