1

i'm learning Assembly on Motorola 68k, i was able to do BubbleSort in ascending order but not descending, i don't know why the program goes into infinite loop; Thx!; The code:

  ORG  $2000
  START LEA  ARRAY,A0
  CLR  D0 *Flag di scambio      
  MOVE.B #L-1,D1 *contatore      
  LOOP  MOVE.B (A0),D2
  MOVE.B 1(A0),D3
  CMP    D2,D3
  BLE    ELSE
  MOVE.B D2,1(A0)
  MOVE.B D3,(A0)
  MOVE.B #1,D0      
  ELSE  ADD  #1,A0
  DBRA D1,LOOP      
  TST D0
  BNE START
  SIMHALT
  ORG  $1000
  ARRAY DC.B 1,5,2,4,3
  L     EQU  5           
  END  START  
  • `BNE START` goes all the way to the start of the program if it's taken, resetting your loop counters. Write down the logic in pseudocode or C to figure out what should be before both loops vs. inside the outer loop. – Peter Cordes Dec 04 '21 at 04:15

1 Answers1

1
      MOVE.B #L-1,D1 *contatore      
LOOP  MOVE.B (A0),D2
      MOVE.B 1(A0),D3
      CMP    D2,D3
      BLE    ELSE
      MOVE.B D2,1(A0)
      MOVE.B D3,(A0)
      MOVE.B #1,D0      
ELSE  ADD    #1,A0
      DBRA   D1,LOOP

Your loop that is based on the D1 contatore runs for too long! In an array that has 5 elements, you can do at most 4 comparisons. That's why you wrote #L-1. However the DBRA instruction repeats until the count is -1, so in this case you still get 5 iterations which is 1 too many. Also your code will read and possibly write memory that does not belong to the array!

i don't know why the program goes into infinite loop;

An "infinite" loop could result from not having initialized the whole 16-bit counter for the DBRA D1,LOOP instruction! Better use MOVE.W #L-1,D1.


When the non-zero D0 register tells you that a change was made to the array, you repeat the whole code. That can work ok, but it is more efficient to realize that the smallest element will have bubbled to the far end and need not be processed any more. The solution is to have an ever decreasing start value for contatore instead of the constant #L-2 (after correction). This way the part of the array that still needs processing becomes shorter and shorter.

START MOVE.W #L-2,D4   *first_contatore

NEXT  LEA    ARRAY,A0
      CLR.L  D0        *Flag di scambio      
      MOVE.W D4,D1     *contatore      
      
LOOP  MOVE.B (A0),D2
      MOVE.B 1(A0),D3
      CMP.B  D2,D3
      BLE    ELSE
      MOVE.B D2,1(A0)
      MOVE.B D3,(A0)
      MOVEQ  #1,D0      
ELSE  ADDQ.L #1,A0
      DBRA   D1,LOOP
      TST.L  D0
      BEQ    DONE      *Nothing was changed, earliest exit
      DBRA   D4,NEXT

DONE  SIMHALT

Tip: Do not neglect the size suffixes. If you move a couple a byte-sized array elements to a couple of data registers, and then compare those registers without specifying the size, the correct result will depend on the defaults that the particular assembler uses. If the default size happens to be .L or .W, then your code will work wrong.
So always state what you need and change CMP D2,D3 into CMP.B D2,D3. A small effort, but a big reward!

Sep Roland
  • 33,889
  • 7
  • 43
  • 76