Metropoli BBS
VIEWER: bubble.asm MODE: TEXT (ASCII)
COMMENT*

 Here's an .EXE program that prints out an array of 16-bit numbers (that
 I just made up), then bubble-sorts them, following Tom's algorithm, and
 then skips a line, and prints the sorted array.  The bubble-sort
 procedure that I wrote works properly only with UNSIGNED numbers.  If
 you want to sort signed numbers, you'll have to change the conditional
 jump statement, at the least.  The number-printing procedure only works
 with unsigned numbers, too...

 for (i1=0; i1<limit; i1++)
     {
     for (i2=i1; i2<limit; i2++)
         {
         if (elem[i1]>elem[i2])
             {
             tmp = elem[1];
             elem[1] = elem[2];
             elem[2] = tmp;
             }
         }
     }
 Written by Julian H. Schmidt - public domain code.
 assembles with MASM.
 For an array of nubmers, like this:  array[limit],
 This will sort the numbers from least to greatest.
 END OF COMMENT*

 ;Equates:
 ELEMENTS = 11

 _data segment para 'DATA'
 array dw 1000,4000,245,15567,23,60789,4321,123,321,6,6543
 Store db 5 dup(0)           ;Storage for ASCII to print.
 CRLF  db 0ah,0dh            ;Carriage Return and Linefeed.
 _data ends

 _code segment para 'CODE'
     assume cs:_code,ds:_data,ss:_stack

 COMMENT*
 BUBBLE - performs a bubble sort on an array of 16-bit integers.
 Entry:
     DS:BX   - Pointer to 1st (word) element of the array.
     AX      - Size of the array (in words).
 Exit:
     Nothing
 Changes:
     Flags, and just about every register but IP, SP, etc. IF IN DOUBT,
     SAVE THE REGISTER BEFORE CALLING THIS PROCEDURE.
 END OF COMMENT*

 Bubble proc    ;This is the sorting procedure.

     mov     cx,ax           ;Size of array in CX for loop control.
     xor     si,si           ;Put a zero in our index register.

 OuterLoop:
     mov     bp,cx           ;BP is our inner-loop iteration counter.
     mov     di,si

 InnerLoop:
     mov     ax,[si+bx]      ;Move array element into AX.
     mov     dx,[di+bx]      ;Move another element into DX.
     cmp     ax,dx           ;Is AX 'above' (unsigned) DX?
     ja      SwitchElements  ;If so, jump and switch the elements.
     jmp     short InnerEnd  ;If not, skip the switch.

 SwitchElements:
     mov     [di+bx],ax      ;Switch two array elements.
     mov     [si+bx],dx      ;  ...they are already in AX and BX!

 InnerEnd:
     add     di,2            ;Point to next array element.
     dec     bp
     cmp     bp,0            ;Is iteration count zero?
     jnz     InnerLoop       ;If not, continue looping...

     add     si,2            ;Point to next array element.
     loop    OuterLoop       ;Loop again (until CX == 0).

     ret                     ;This procedure is finit!
 bubble endp

 ;----------------------------------------------------
 ; Procedure DisplayDecimal                          |
 ; Entry: BX= number to display in decimal           |
 ; Exit : Registers corrupt                          |
 ; This will not check the thousandths place...      |
 ; This procedure courtesy of someone in 80XXX?      |
 ;----------------------------------------------------
 DisplayDecimal proc        ;Beginning of procedure DisplayDecimal.
     mov    ax,10000        ;First check ten-thousandths place.
     xor    cx,cx
 dd_loop1:
     xor    dx,dx           ;Clear DX so that DX:AX = AX.
     mov    cl,0FFh         ;Start counter at -1 (signed).
 dd_loop2:
     inc    cl              ;At least one increment to zero.
     sub    bx,ax           ;Subtract the place representor
                            ; from the test value.
     jnc    dd_loop2        ;If the result isn't negative keep going.
     add    bx,ax           ;Add to make the test value
                            ; non-negative (restore).
                            ;This brings it back to the original value.
 dd_noadd:                  ;Digit is now in CL...
     add    cl,30h          ;Add ASCII '0'.
                            ;Now, CL holds Ascii value of the number.
     push   cx              ;Put the digit on the stack.
                        ;Number will be on stack in the reverse order.
     mov    cx,10
     idiv   cx              ;divide DX:AX by 10, result in AX,
                            ; remainder in DX
     or     ax,ax       ;Test if AX is zero (1 div 10 = 0 remainder 1)
     jnz    dd_loop1        ;If not do the next place.

                     ;Now, I must pop the 5 digits and store them...
     mov    cx,5
 StoreLoop:
     pop    ax              ;Get a digit from the stack
     mov    bx,offset Store
     add    bx,cx
     dec    bx
     mov    byte ptr[bx],al ;Store the digit.
     loop   StoreLoop

 RET            ; else return
 DisplayDecimal endp        ;End of procedure DisplayDecimal.
 ;----------------------------------------------------------------------
 bub proc                   ;This is the program entry point.
     mov    ax,_data        ;Make our data segment accessible.
     mov    ds,ax
     mov    cx,ELEMENTS     ;CX is for loop control.
     xor    si,si           ;SI used for indexed addressing.
 PrintLoop1:                ;Print out the initial (unsorted) array:
     mov    bx,[array+si]   ;Get the element into BX.
     push   cx              ;Save our loop control register.
     call   DisplayDecimal  ;Translate to ASCII.
     mov    ah,40h          ;Request function 40h (DOS).
     mov    bx,0001         ;Standard Output Handle in BX.
     mov    cx,7            ;Print out 5 characters (+CRLF).
     mov    dx,offset Store ;DX is pointer to data.
     int    21h             ;Dos's Output to Device (Handle).
     pop    cx              ;Restore loop-control register.
     add    si,2            ;Point SI to next word in array.
     loop   PrintLoop1      ;Loop while elements exist to print.
     mov    ax,ELEMENTS     ;AX gets length of the array.
     lea    bx,array        ;Point BX to the array beginning.
     call   bubble          ;Sort the sucker.
     mov    ah,40h          ;Request function 40h (DOS).
     mov    bx,0001         ;Standard Output.
     mov    cx,2            ;Number of bytes to print out.
     mov    dx,offset CRLF  ;Point DX to data to print.
     int    21h             ;Dos's Output to Device (STDOUT)
     mov    cx,ELEMENTS     ;CX is for loop control.
     xor    si,si           ;SI used for indexed addressing.
 PrintLoop2:
     mov    bx,[array+si]   ;Get the element into BX.
     push   cx              ;Save our loop-control register.
     call   DisplayDecimal  ;Translate to ASCII.
     mov    ah,40h          ;Request function 40h (DOS).
     mov    bx,0001         ;Standard Output Handle in BX.
     mov    cx,7            ;Print out 5 characters (+CRLF).
     mov    dx,offset Store ;DX is pointer to data.
     int    21h             ;Dos's Output to Device (Handle).
     pop    cx              ;Restore loop-control register.
     add    si,2            ;Go to next word in array.
     loop   PrintLoop2      ;Print out all of the sorted elements.
     mov    ax,4c00h        ;Request function 4Ch (DOS).
     int    21h             ;Dos's Terminate program function.
 bub endp
 _code ends
 _stack segment 'STACK'
     db 100 dup('STACK')
 _stack ends
 End bub

[ RETURN TO DIRECTORY ]