sortingassemblyemu8086flowchart

bubble sort in emu8086


The flowchart below is used to sort in ascending order an array of length N = 100h starting at address [200h], following the principle:

Principle:

Sort each pair of successive values in the array (if they are not sorted in ascending order, swap them).

For each value of the secondary counter DX, the values to be sorted are pointed to by [SI] and [SI + 1]. Since the array has N values and the first pass is done comparing between the second-to-last and the last value, the primary counter CX will have to traverse (N - 1) values, i.e., CX = N - 1, N - 2, ..., 2, 1. This solution allows stopping the process when it is observed that the array is already sorted after one pass of the secondary counter DX through all its relevant values, even before reaching the limit of the primary counter (CX = 1).

For each pass (i) (meaning for each value of the primary counter CX = N - i), SI varies from its initial value (200h) to the value (200h + N - i - 1), giving (N - i) values. Therefore, the counter DX will take the following (N - i) values:

This translates to:

DX = N - i, N - i - 1, N - i - 2, ..., 2, 1
DX = CX, CX - 1, CX - 2, ..., 2, 1

The flowchart:

start 
cx=n-1
 
 etq:
 dx=cx
 si=200h
 bl=0
 
 al=[si]
 
 bcl:
 al<=[si+1]
   if yes:
     si=si+1
     dx=dx-1
   if no:
     permute al,[si+1]
     si=al
     bl=bl+1
     si=si+1
     dx=dx-1
    
  zf=1 ?
      if yes:
        bl=0?
          if yes:
            end
          if no:
            cx=cx-1
            z=1?
            if yes:
               end
            if no:
               etq      
      if no:
        bcl 

i tried translating it to the code below:

; multi-segment executable file template.

data segment
    tab db 30h,35h,23h,37h,38h,39h,31h
    n dw 7
ends

stack segment
    dw   128  dup(0)
ends

code segment
start:
; set segment registers:
    mov ax, data
    mov ds, ax
    mov es, ax
    
    sub n,1
    mov cx,n 
    etq:
    mov dx,cx
    mov si,200h
    mov bl,0  
    
    mov al,[si]
    bcl:
    cmp al,[si+1]
    jbe con
    
    mov dl,al
    mov al,[si+1]
    mov [si+1],dl  
    
    mov si,ax
    inc bl
    
    con:
    inc si
    dec dx
        
    jnz bcl
    
    cmp bl,0
    je fin
    dec cx
    
    jnz bcl 
   
    fin:
    mov ax, 4c00h ; exit to operating system.
    int 21h    
ends

end start ; set entry point and stop the assembler.
           

but it doesn't change anything.


Solution

  • Sort each pair of successive values in the array (if they are not sorted in ascending order, swap them).

    Because you erroneously keep mov al,[si] outside of the bcl loop, you are not processing pairs of successive values. You end up comparing between non-adjacent elements.

    Sort each pair of successive values in the array (if they are not sorted in ascending order, swap them).

    Because you erroneously use mov si,ax based on an error in the pseudo code, the pointer SI gets destroyed and there's no telling what the results will be. The correct instruction is mov [si], al.

    dec cx
    jnz bcl
    

    Here the pseudo code had it right, but you erroneously wrote bcl instead of etq. I find these names bcl (boucle) and etq (étiquette) a bit too generic. Might I suggest InnerLoop and OuterLoop ?

    mov dl,al
    

    You shouldn't use the DL register within the inner loop since you are already using DX as the inner loop counter. Remember that DL is the low byte of DX, just like DH is the high byte of DX.

    One solution

        dec  n
        mov  cx, n 
    OuterLoop:
        mov  dx, cx
        mov  si, 0200h
        mov  bl, 0  
    InnerLoop:
        mov  ax, [si]     ; Read two adjacent byte-sized elements
        cmp  al, ah       ; Compare
        jbe  con
        mov  [si+1], al   ; Swap low -> high
        mov  [si], ah     ; Swap high -> low
        mov  bl, 1        ; Testify the swap
    con:
        inc  si
        dec  dx
        jnz  InnerLoop
        
        test bl, bl
        jz   fin
        dec  cx
        jnz  OuterLoop
    fin:
    

    I have replaced your inc bl by mov bl, 1. Both instructions are the same length, but the inc bl could backfire on you (producing a so-called 'false positive') in case the number of swap operations happens to be a multiple of 256.

    [edit]

    the elements didn't really change their order.

    The task description talks about an array located at address 200h, but the program that you have written has placed the array behind its own label and that happens to be at offset address 0 in the data segment.
    Either you satisfy the task description by adding a filler:

        db 200h dup(0)
    tab db 30h,35h,23h,37h,38h,39h,31h
    n   dw 7
    

    or you don't add a filler and just replace mov si, 0200h by mov si, OFFSET tab.