KidKool
KidKool

Reputation: 43

assembly: sorting numbers using only conditional statments

I am new to assembly and I am trying to write a program that gets five user inputed numbers, stores them in variables num1-num5, sorts them(without using arrays) with num5 having the greatest value and num1 having the lowest value, and then displays the sorted numbers. I am having trouble figuring out how to approach this. I got the 5 numbers and stored them in the variables but I am confused as to how to start with sorting. I have tried a few things but I keep getting errors. This is my code that I can actually get running but it isn't working the way I want it to.

  TITLE MASM Template        (main.asm) 

   INCLUDE Irvine32.inc 
 .data 



  getnumber byte "Please enter a number between 0 and 20",0ah,0dh,0 




 num1 byte  0
 num2 byte  0
 num3 byte  0
 num4 byte  0
 num5 byte  0 


 .code 
  main PROC 
call Clrscr 
;************* get the information from the user******************* 


mov edx, offset getnumber      ;ask to input number 
call writestring 
call readint 
mov bl, al  
mov num1, bl               ;get the number and move to num1 variable 

mov edx, offset getnumber      ;ask to input number 
call writestring 
call readint 
mov bl, al
mov num2, bl                ;get the number and move to num2 variable

mov edx, offset getnumber      ;ask to input number 
call writestring 
call readint 
mov bl, al 
mov num3, bl                ;get the number and move to num3 variable


    mov edx, offset getnumber    ;ask to input number
call writestring 
call readint 
mov bl,al
mov num4, bl             ;get the number and move to num4 variable

mov edx, offset getnumber      ;ask to input number 
call writestring 
call readint 
mov bl, al
mov num5, bl              ;get the number and move to num5 variable



;***show the user inputed numbers****
mov al, num1 
call writeint 

mov al, num2 
call writeint 

mov al,num3 
call writeint 

mov al, num4 
call writeint 

mov al,num5 
call writeint 

;*****start comparing***
cmp bl,num5
jl jumptoisless
    jg jumptoisgreater

jumptoisless:

call writeint

jumptoisgreater:
mov bl, num5
mov dl, num4

mov num5, dl
mov num4,  bl

call writeint 

jmp imdone


    imdone:
    call dumpregs

     exit 
    main ENDP 

    END main

Upvotes: 0

Views: 376

Answers (1)

Ped7g
Ped7g

Reputation: 16596

Some notes to your code:

call readint 
mov bl, al
mov num2, bl

Why don't you simply store al directly to memory, as: mov [num2],al? You don't use the bl anyway.


Except here:

;*****start comparing***
cmp bl,num5
jl jumptoisless
jg jumptoisgreater

Where I would be afraid what call writeint does to ebx (or you did your homework, and you know from head that call writeint preserves ebx content?).

And if the ebx is preserved, then bl contains still num5 from the input, so it will be equal.

Funnily enough, when equal, you will continue with jumptoisless: part of code, which will output some leftover in al, and then it will continue to jumptoisgreater: part of code, so effectively executing all of them.

Can you watch the CPU for a while in debugger, while single stepping over the instructions, to understand a bit better how it works? It's a state machine, ie. based on the current values in registers, and content of memory, it will change the state of registers and memory in the deterministic way.

So unless you jump away, next instructions is executed after the current one, and jl + jg doesn't cover "equal" state (at least you do cmp only once, so hopefully you understand the jcc instructions don't change flags and both jl/jg operate on the same result of cmp in flags). The Assembler doesn't care about name of your labels, and it will not warn you the "isgreater" code is executed even when "isless" was executed first.

About how to solve your task:

Can't think of anything reasonably short, unless you start to work with num1-num5 memory as array, so you can address it in generic pointer way with index. So I will gladly let you try on your own, just a reminder you need at least n*log_n compares to sort n values, so if you would write very effective sort code, you would need at least 5*3 = 15 cmp instructions (log2(5) = 3, as 23 = 8).

On the other hand an ineffective (but simple to write and understand) bubble sort over array can be done with single cmp inside two loops.


rcgldr made me curious, so I have been trying few things...

With insertion sort it's possible to use only 8x (at most) cmp (I hope the pseudo-syntax is understandable for him):

Insert(0, num1)
// ^ no cmp
Insert((num2 <= [0] ? 0 : 1), num2)
// ^ 1x cmp executed
Insert((num3 <= [0] ? 0 : (num3 <= [1] ? 1 : 2)), num3)
// ^ at most 2 cmp executed
Insert((num4 <= [1] ? (num4 <= [0] ? 0 : 1) : (num4 <= [2] ? 2 : 3)), num4)
// ^ always 2 of 3 cmp executed
Insert((num5 <= [1] ? (num5 <= [0] ? 0 : 1) : (num5 <= [2] ? 2 : (num5 <= [3] ? 3 : 4))), num5)
// ^ at most 3 of 4 cmp executed

=> total at most 8 cmp executed.

Of course doing the "insert" with "position" over fixed variables would be total PITA... ;) So this is half-joke proposal just to see if 8x cmp is enough.

("6 compares" turned out to be my brain-fart, not possible AFAIK)

Upvotes: 2

Related Questions