2

I am trying to iterate an array and find numbers less than, equal to, and more than to be stored. I want to store the count in the three results and if possible display the result

    ORG     $1000
    
    START:  ORG $2000                ; first instruction of program
        LEA DATA,A0 
        MOVE.B #9,D0 
        CLR.B D1 
        CLR.B D2
        CLR.B D3
            
    LOOP:   MOVE.B (A0)+,D4 
        CMP.B #50,D4 
        BGT GRT_50
        BLT LESS_50
        BEQ EQ2
        LOOP

    GRT_50: ADD.B #1,D3      
        BNE LOOP   

            
   LESS_50: ADD.B #1,D01
        BNE LOOP  
                        
    GRT_50: ADD.B #1,D2    
        BNE LOOP   
        STOP    #2000   


    

* Put variables and constants here
     ORG        $2000
DATA    DC.B    $55,$10,$20,$30,$40,$50,$60,$65,$70,$80
RESULT1 DC.B    $0
RESULT2 DC.B    $0
RESULT3 DC.B    $0
END    START   ; last line of source

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
amolc
  • 33
  • 1
  • 7
  • Does this assemble? – Erik Eidt Feb 27 '22 at 15:16
  • You need to use an unconditional branch to return to the loop top, but you're using a conditional branch! – Erik Eidt Feb 27 '22 at 15:16
  • @ErikEidt , can you help me know the mistake. – amolc Feb 28 '22 at 00:22
  • You made quite a few mistakes, e.g., `LOOP` is not an instruction, use `dbf d0,LOOP` instead (you need to `move.w #9,d0` for that to work, or just `moveq #9,d0`). You defined the label `GRT_50` twice. There is no `d01` register. Your program logic has flows as well, but try to get your code actually running, first. – chtz Feb 28 '22 at 09:18
  • 1
    If you're just going to hold the counts of each category in a register, you don't really need to reserve bytes to store that data in your memory. – puppydrum64 Feb 01 '23 at 16:03

1 Answers1

2

Okay, let's take a look at some of the mistakes here:

  • Only one ORG statement at a time. Start with ORG $1000 or ORG $2000 but not both. Just make sure to use an address for data that won't overlap to avoid overwriting stuff.
  • Use DBRA D0,LOOP to loop (in this case 10 times) to the LOOP label.
  • Use BRA LOOP instead of BNE LOOP, as BNE is a conditional jump.
  • MOVE #9,D0 without the .b to use it correctly with DBRA, because DBRA uses a word-sized counter. When you just write .b you can't be sure what the upper 8 bits of the word happen to be.
  • At BEQ EQ2 you try to jump to the label EQ2, but there is no such.
  • There is no D01 register, use ADD #1,D1. As already mentioned.

And some notes:

  • I would skip the .b at "CLR.B" and "ADD.B" as it unnecessarily shrinks the counting variables from word to byte size. Note that the 68k can work with byte, word and long sizes, and defaults to word-size most of the time.
  • As you use Hex Numbers in the data field, I think you want to compare it to Hex 50 (CMP #$50,D4) instead of decimal 50.
  • The addresses $1100 and $1110 in my example code are arbitrary. In Easy68k they can nicely be observed in the memory window.

Many of these have already been stated in the comments, but I'm trying to summarize everything here.

There is still room for improvement, but I'd maybe write it like this:

    ORG    $1000    
START:
    LEA DATA,A0     ;set A0 to data address
    MOVE #10-1,D0   ;setup for 10 iterations          
LOOP:
    MOVE.B (A0)+,D1 ;fetch byte
    CMP.B #$50,D1   ;compare
    BGT GRT_50      ;and branch conditionally
    BLT LESS_50
    BEQ EQUAL_50 
CONT: 
    DBRA D0, LOOP   ;come back here to loop
    SIMHALT         ;stop

GRT_50: 
    ADD #1, RESULT_G    
    BRA CONT            
LESS_50: 
    ADD #1, RESULT_L
    BRA CONT
EQUAL_50:
    ADD #1, RESULT_E    
    BRA CONT
       
* data and vars

    ORG $1100
DATA      DC.B    $55,$10,$20,$30,$40,$50,$60,$65,$70,$80
    ORG $1110
RESULT_G  DC.W    $0
RESULT_L  DC.W    $0
RESULT_E  DC.W    $0
    END      Start
Sep Roland
  • 33,889
  • 7
  • 43
  • 76
Steve_I
  • 51
  • 7
  • Counting in registers and only storing at the end is usually more efficient even though it takes more code size. The difference would be larger for a longer array, where you spend more time in the loop compared to setup / cleanup. If you are going to use memory, it could be worth it to generate a 0 or 1 integer based on the compare, and use that to index which counter to increment. So maybe branch on equal, but use greater vs. less as an index for the common case? I'd have to check instruction timings from real 68k CPUs; removing 2 branches that can mispredict would help later CPUs more. – Peter Cordes Mar 05 '23 at 05:51
  • You could at least put one of the cases inline; if it's not greater or less, it must be equal so no need to actually branch on all three. – Peter Cordes Mar 05 '23 at 05:51
  • 1
    (Welcome to Stack Overflow, BTW. Note that old total-beginner questions like the one you answered are often from people doing homework or something, and the original author of the question already learned the answer by now, or has finished the course and isn't interested anymore. With super specific questions like this, it's rare that any other future readers will find it and benefit, so answering year-old questions like this one is mostly just a learning exercise for yourself. Which is fine, but keep that in mind when deciding what to write. This nice answer won't get many eyeballs :/) – Peter Cordes Mar 05 '23 at 05:52
  • 1
    You are right, of course counting in registers is much faster and addq is faster than add, and so on. I deliberately wanted to keep the code simple (and a bit close to the original) because a beginner asked. I am currently twiddling with 68k asm and these are nice exercises. I was aware the question is outdated, but I still hope that every once in a while it helps somebody taking their first steps. Thanks for the nice welcome Peter! =) – Steve_I Mar 06 '23 at 17:55