Efficient LC3 assembly code to print the numbers leading up to any digit

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
1
down vote

favorite












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?







share|improve this question



























    up vote
    1
    down vote

    favorite












    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?







    share|improve this question























      up vote
      1
      down vote

      favorite









      up vote
      1
      down vote

      favorite











      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?







      share|improve this question













      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?









      share|improve this question












      share|improve this question




      share|improve this question








      edited Feb 9 at 13:21









      Jamal♦

      30.1k11114225




      30.1k11114225









      asked Feb 9 at 5:35









      shiftybits

      85




      85




















          1 Answer
          1






          active

          oldest

          votes

















          up vote
          1
          down vote



          accepted










          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"





          share|improve this answer























            Your Answer




            StackExchange.ifUsing("editor", function ()
            return StackExchange.using("mathjaxEditing", function ()
            StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
            StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
            );
            );
            , "mathjax-editing");

            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "196"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            convertImagesToLinks: false,
            noModals: false,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );








             

            draft saved


            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f187152%2fefficient-lc3-assembly-code-to-print-the-numbers-leading-up-to-any-digit%23new-answer', 'question_page');

            );

            Post as a guest






























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            1
            down vote



            accepted










            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"





            share|improve this answer



























              up vote
              1
              down vote



              accepted










              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"





              share|improve this answer

























                up vote
                1
                down vote



                accepted







                up vote
                1
                down vote



                accepted






                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"





                share|improve this answer















                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"






                share|improve this answer















                share|improve this answer



                share|improve this answer








                edited Feb 15 at 11:55


























                answered Feb 14 at 16:34









                Fifoernik

                27827




                27827






















                     

                    draft saved


                    draft discarded


























                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f187152%2fefficient-lc3-assembly-code-to-print-the-numbers-leading-up-to-any-digit%23new-answer', 'question_page');

                    );

                    Post as a guest













































































                    Popular posts from this blog

                    Greedy Best First Search implementation in Rust

                    Function to Return a JSON Like Objects Using VBA Collections and Arrays

                    C++11 CLH Lock Implementation