News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Comparing two values

Started by arsenalftw067, October 19, 2015, 01:26:25 PM

Previous topic - Next topic

arsenalftw067

Hi, I'm fairly new to using assembly

How do you compare two values in an array? To compute if it's greater than, less than, equal?

Is there a predefined library? I was thinking of moving one value into a register, the next value into another register, and subtracting the two, so if the result is greater than 0, that means the first value is greater than the second, if it's less than 0 then that means the second value is greater

Basically, I have an array with random integers, and I need to sort them from lowest to highs using a stack

How do you use conditions?? In C++ I can do a simple if else condition, but in assembly?

hutch--

Two array values are both memory operands so you must load at least one into a register (this is assuming that the array sizes are 32 bit.)

In the simplest,

    mov eax, arr1
    cmp arr2, eax
  ; next is the size test
    jg greater
    je equal
    jl lesser
  ; You have 3 matching labels for each of the 3 jumps if you use all 3.


It can be done with .IF notation but the comparison must still be a register for one and the operand for the other.

arsenalftw067

Hm, so how would I implement the different jump conditions?

I'm confused, I feel like I would have to store the first element in a registry, and then go through the whole array comparing each element to the first, and if the first one is greater than all of them, I would push it onto a stack

so at the end I would pop the stack and the array would be sorted from lowest to highest

Raistlin

Hi and welcome arsenalftw067 (what a handle !)

anyhow - please could you inform us what size the array expected (number of values) and
type of values (integer range ex. -32768 to + 32768) to sort. This would
help immensely in assisting you.

Thanks
Raistlin   
Are you pondering what I'm pondering? It's time to take over the world ! - let's use ASSEMBLY...

arsenalftw067

its a BYTE size array with 7 elements (starting from 1, not 0, so since the first index is 0 the size is 6)

the elements are represented as decimals, and they are all unsigned, 8 bit integers so it would range from -256 to 256

Neil

Sounds like what you need is a 'Bubble Sort'

Here is an example:-

    mov count,n              ;prime counter (n = numbers in array)

A1: dec count               ;numbers to sort = numbers to sort-1
      je done                  ;all done? yes, finish
      mov ebx,1              ;exchange taken place indicator
     mov ecx,count         ;prime counter with numbers left to sort
     lea esi,array             ;point array

A2: mov al,[esi]            ;get number
     inc esi                    ;inc pointer
     cmp [esi],al            ;compare with number above
     ja @F                     ;if higher bypass exchange
    xchg [esi],al            ;mov higher number up
    mov [esi-1],al          ;mov lower number down
    xor ebx,ebx             ;indicate exchange has taken place

@@: dec ecx               ;numbers left to sort = numbers left to sort-1
        jne A2                 ;all done ? no, loop again
        test ebx,0            ;exchange taken place ?
        je A1                    ;yes, loop for next

done:                         ;End of sort

jj2007

Quote from: arsenalftw067 on October 19, 2015, 04:45:51 PMI'm confused, I feel like I would have to store the first element in a registry, and then go through the whole array comparing each element to the first, and if ...

Up to this point, you seem not at all confused :bgrin:

Here is a template for playing around. You might start with a bubble sort, as suggested by Neil. The commented part between pushad & popad is for printing current values.

Neil has used the jxx instructions, while this template uses .if ... .else ... .endif syntax. Under the hood (in a debugger like Olly) it looks like Neil's code, but for grasping the logic, .if .. .endif is easier IMO. You can always translate the .if .. .endif into jxx.

include \masm32\include\masm32rt.inc

.data
MyArray BYTE 5, 0, 3, 7, 99, 2, 6

.code
start:
  mov ebx, 0 ; outer counter
  .Repeat
mov al, MyArray[ebx]
mov ecx, 0 ; inner counter
.Repeat
cmp al, MyArray[ecx]
.if Sign? ; eax is smaller
nop ; which action?
.else
nop ; action or not?
.endif
inc ecx
; pushad
; movzx eax, MyArray[ebx]
; print str$(eax), " "
popad
.Until ecx>sizeof MyArray
inc ebx
  .Until ebx>=sizeof MyArray
  print chr$(13, 10, "OK, it should be sorted now", 13, 10)
  mov ebx, 0
  .Repeat
movzx eax, MyArray[ebx]
print str$(eax), " "   ; time to show the results ;-)
inc ebx
  .Until ebx>=sizeof MyArray
  MsgBox 0, "We made it...", "Hello World", MB_OK
  exit

end start

dedndave

;for 8 or fewer byte-sized elements, we can do an in-register bubble sort
;in this case, we want to sort 7 bytes
;first, we want to load the 7 byte values into registers
;for 6 of them, we can load 2 at a time as words
;notice that we preserve EBX, the other registers are considered "volatile"
;that gives us 8 byte registers to work with: AL, AH, BL, BH, CL, CH, DL, DH

    push    ebx
    mov     ax,word ptr MyArray[0]    ;word ptr is used to override byte defined array
    mov     cx,word ptr MyArray[2]
    mov     dx,word ptr MyArray[4]
    mov     bl,MyArray[6]

;now, we use bubble sort to order the byte elements
;normally this is done in a loop, to handle larger arrays
;by examining the code for in-register sort, you get a feel for how the loop works
;when done, we want the following order:

;AL = lowest element
;AH
;CL
;CH
;DL
;DH
;BL = highest element

;first "loop pass" (bottom to top)
;at the end of this pass, the highest element will be in BL
;on the next pass, we no longer need to sort that value
;this is why each pass gets shorter by 1 element

    .if al>ah
        xchg    al,ah
    .endif
    .if ah>cl
        xchg    ah,cl
    .endif
    .if cl>ch
        xchg    cl,ch
    .endif
    .if ch>dl
        xchg    ch,dl
    .endif
    .if dl>dh
        xchg    dl,dh
    .endif
    .if dh>bl
        xchg    dh,bl
    .endif

;second "loop pass" (top to bottom)
;at the end of this pass, the lowest element will be in AL

    .if dh<dl
        xchg    dh,dl
    .endif
    .if dl<ch
        xchg    dl,ch
    .endif
    .if ch<cl
        xchg    ch,cl
    .endif
    .if cl<ah
        xchg    cl,ah
    .endif
    .if ah<al
        xchg    ah,al
    .endif

;third "loop pass" (bottom to top)
;at the end of this pass, the second highest element will be in DH

    .if ah>cl
        xchg    ah,cl
    .endif
    .if cl>ch
        xchg    cl,ch
    .endif
    .if ch>dl
        xchg    ch,dl
    .endif
    .if dl>dh
        xchg    dl,dh
    .endif

;forth "loop pass" (top to bottom)
;at the end of this pass, the second lowest element will be in AH

    .if dl<ch
        xchg    dl,ch
    .endif
    .if ch<cl
        xchg    ch,cl
    .endif
    .if cl<ah
        xchg    cl,ah
    .endif

;fifth "loop pass" (bottom to top)
;at the end of this pass, the third highest element will be in DL

    .if cl>ch
        xchg    cl,ch
    .endif
    .if ch>dl
        xchg    ch,dl
    .endif

;sixth "loop pass" (top to bottom)
;at the end of this pass, the third lowest element will be in CL
;and the forth lowest element will be in CH

    .if ch<cl
        xchg    ch,cl
    .endif

;now, we place the elements back into the array, much the same way we loaded them

    mov word ptr MyArray[0],ax
    mov word ptr MyArray[2],cx
    mov word ptr MyArray[4],dx
    mov     MyArray[6],bl
    pop     ebx

arsenalftw067

Thank you guys for the reply! Unfortunately a lot of what you guys are offering are a bit advanced and my professor wants it to be done using simple methods.

Currently, my code executes but it does not do the sorting correctly, showing the final outcome to be: 00 00 00 00 14 0A 78, which is completely incorrect.

The final result, after all those 00, shows the first 3 elements of the original array:

20 10 60 5 120 90 100

Which means the sorting didn't even attempt to sort, and for some reason adds a bunch of 0's


array BYTE 20, 10, 60, 5, 120, 90, 100 ; array with 6 values
arraysize = ($ - array) -1 ; size of array

.code
main PROC
mov esi, OFFSET array
mov ecx, arraysize;
call SortArray

SortArray PROC

L1:
push ecx
mov edi, esi ; use seond pointer
mov eax, [esi]
L2:
add edi, 2
CMP eax, [edi]; compare second value with previous
JGE exchg ; perform exchange
JLE dntxchg ; dont perform exchange

add esi, 2
pop ecx
loop L1

dntxchg:
loop L2 ; start loop again

exchg:
mov eax, [edi]
xchg [esi], eax
mov [edi], eax
loop L2 ;

jj2007

Would you please post the complete code, from include ... to ... end start?

arsenalftw067


TITLE Sort array (Array.asm)

; This program sorts an array with random integers
; and outputs them in order

INCLUDE Irvine32.inc ; new
includelib C:\Irvine\Kernel32
includelib C:\Irvine\User32
includelib C:\Irvine\Irvine32

.data
array BYTE 20, 10, 60, 5, 120, 90, 100 ; array with 6 values
arraysize = ($ - array) -1 ; size of array

.code
main PROC
mov esi, OFFSET array
mov ecx, arraysize;
call SortArray

SortArray PROC

L1:
push ecx
mov edi, esi ; use seond pointer
mov eax, [esi]
L2:
add edi, 2
CMP eax, [edi]; compare second value with previous
JGE exchg ; perform exchange
JLE dntxchg ; dont perform exchange

add esi, 2
pop ecx
loop L1

dntxchg:
loop L2 ; start loop again

exchg:
mov eax, [edi]
xchg [esi], eax
mov [edi], eax
loop L2 ;


SortArray ENDP

;show contents of array
mov esi, OFFSET array
mov ecx, arraysize
inc ecx
L3:
mov ebx, TYPE array
call DumpMem
loop L3

call DumpRegs ; display the registers
call WaitMsg        ; Pause until a key is pressed
exit
main ENDP
END main

jj2007

A proc inside a proc... astonishing that the assembler doesn't complain! Split them, and make sure that SortArray has a ret at the end. Then start searching the bug. You need some routine to print results, dumping regs won't help. Who suggested to use the Irvine lib? Masm32 would be much better.

main PROC
mov esi, OFFSET array
mov ecx, arraysize;
call SortArray

SortArray PROC
...
SortArray ENDP
...
call DumpRegs ; display the registers
call WaitMsg        ; Pause until a key is pressed
exit
main ENDP

arsenalftw067

Are there any issues with the logic of the code?

arsenalftw067

The issue is that the sorting is not actually implementing correctly but I don't know why