Sorting Arrays and Processing their Sizes and Addresses as Stack Arguments
INCLUDE Irvine32.inc
.DATA
header1 BYTE "Data for Array1 ", 0dh, 0ah, 0
header2 BYTE "Data for Array2", 0dh, 0ah, 0
msg1 BYTE "----------------", 0dh, 0ah, "Initial array:", 0dh, 0ah, 0
msg2 BYTE "Sorted array:", 0dh, 0ah, 0
msg3 BYTE "Number of comparisons: ", 0
msg4 BYTE 0dh, 0ah, "Number of swaps: ", 0
separator BYTE ", ",0
array1 DWORD 20 DUP(0) ; array of pointers to strings
array2 DWORD 20 DUP(0)
buffer BYTE 300 DUP(0) ; place to save generated strings
bufpos DWORD 0 ; current free position in buffer
min DWORD 0
; stats data
swaps DWORD 0
comps DWORD 0
.CODE
main PROC
call Randomize ; initialize random generator
; Fill first arrray
mov eax, 20 ; pass size of array to fill
push eax
mov eax, OFFSET array1 ; pass array to fill
push eax
call FillRandomArray ; fill the array with random strings
add esp, 8 ; remove arguments from stack
mov edx, OFFSET header1 ; load header string address
call WriteString ; print on screen
mov edx, OFFSET msg1 ; load initial array message address
call WriteString ; print on screen
; Print first arrray
mov eax, 20 ; pass size of array to print
push eax
mov eax, OFFSET array1 ; pass array to print
push eax
call PrintArray ; print the array
add esp, 8 ; remove arguments from stack
mov eax, 20 ; pass size of array to sort
push eax
mov eax, OFFSET array1 ; pass array to sort
push eax
call PairBubbleSort ; sort using pair bubble sort
add esp, 8 ; remove arguments from stack
mov edx, OFFSET msg2 ; load sorted array message address
call WriteString ; print on screen
; Print sorted first array
mov eax, 20 ; pass size of array to print
push eax
mov eax, OFFSET array1 ; pass array to print
push eax
call PrintArray ; print the array
add esp, 8 ; remove arguments from stack
; Print statistics for first array
mov edx, OFFSET msg3 ; load comparison stats string address
call WriteString ; print on screen
mov eax, [comps] ; load comparisons
call WriteDec ; print on screen
mov edx, OFFSET msg4 ; load swap stats string address
call WriteString ; print on screen
mov eax, [swaps] ; load swaps
call WriteDec ; print on screen
call CrLF
call CrLF
; Fill second arrray
mov eax, 20 ; pass size of array to fill
push eax
mov eax, OFFSET array2 ; pass array to fill
push eax
call FillRandomArray ; fill the array with random strings
add esp, 8 ; remove arguments from stack
mov edx, OFFSET header2 ; load header string address
call WriteString ; print on screen
mov edx, OFFSET msg1 ; load initial array message address
call WriteString ; print on screen
; Print second arrray
mov eax, 20 ; pass size of array to print
push eax
mov eax, OFFSET array2 ; pass array to print
push eax
call PrintArray ; print the array
add esp, 8 ; remove arguments from stack
mov eax, 20 ; pass size of array to sort
push eax
mov eax, OFFSET array2 ; pass array to sort
push eax
call ListBubbleSort ; sort using list bubble sort
add esp, 8 ; remove arguments from stack
mov edx, OFFSET msg2 ; load sorted array message address
call WriteString ; print on screen
; Print sorted second array
mov eax, 20 ; pass size of array to print
push eax
mov eax, OFFSET array2 ; pass array to print
push eax
call PrintArray ; print the array
add esp, 8 ; remove arguments from stack
; Print statistics for second array
mov edx, OFFSET msg3 ; load comparison stats string address
call WriteString ; print on screen
mov eax, [comps] ; load comparisons
call WriteDec ; print on screen
mov edx, OFFSET msg4 ; load swap stats string address
call WriteString ; print on screen
mov eax, [swaps] ; load swaps
call WriteDec ; print on screen
call CrLF
exit ; exit the program
main ENDP
; Fill an array with random strings
; Prototype: FillRandomArray(array, n)
FillRandomArray PROC
push ebp ; save frame pointer
mov ebp, esp ; create new stack frame
push ecx ; save used registers
push esi
mov esi, [ebp + 8] ; load array pointer
mov ecx, [ebp + 12] ; load array size
fill_loop:
call GenerateRandomStr ; generate a random string
mov [esi], eax ; save pointer in array
add esi, 4 ; advance to next position
loop fill_loop ; repeat for all entries
pop esi ; restore used registers
pop ecx
pop ebp ; restore frame pointer
ret
FillRandomArray ENDP
; Generates a random string of length 2 to 7
; Prototype: char *GenerateRandomStr()
; uses the global buffer and bufpos
GenerateRandomStr PROC
push ecx ; save used registers
push esi
push edi
mov eax, 6 ; generate number between 0 and 5 for length
call RandomRange
add eax, 2 ; add 2 to get range 2 to 7
mov edi, OFFSET buffer ; point to start of buffer
add edi, [bufpos] ; advance to current position in array
mov esi, edi ; save start position in esi
mov ecx, eax ; copy to loop counter
gen_loop:
mov eax, 62 ; generate number between 0 and 61 for character
call RandomRange
cmp eax, 26 ; if number is between 0 and 26
jl saveLo ; save lowercase
cmp eax, 52 ; if number is between 26 and 52
jl saveHi ; save uppercase
saveDigit:
sub eax, 52 ; subtract 52 to get value 0-9
add eax, 48 ; convert to ascii
jmp save
saveLo:
add eax, 'a' ; convert number to lowercase letter
jmp save
saveHi:
sub eax, 26 ; subtract 26 to get value 0-25
add eax, 'A' ; convert number to lowercase letter
jmp save
save:
mov [edi], al ; save char in string
inc edi ; advance to next position in buffer
inc [bufpos] ; increment global buffer position
loop gen_loop ; loop for the length of the string
mov BYTE PTR [edi], 0 ; save end of string
inc [bufpos] ; increment global buffer position
mov eax, esi ; return the initial pointer
pop edi ; restore used registers
pop esi
pop ecx
ret
GenerateRandomStr ENDP
; Sorts an array using pairwise bubble sort
; Prototype: PairBubbleSort(array, n)
PairBubbleSort PROC
push ebp ; save frame pointer
mov ebp, esp ; create new stack frame
push ebx ; save used registers
push ecx
push edx
push esi
mov DWORD PTR [swaps], 0 ; reset swap count
mov DWORD PTR [comps], 0 ; reset comparison count
mov esi, [ebp + 8] ; load array pointer
mov ecx, [ebp + 12] ; load array size n in j index
dec ecx ; use j = n - 1
for_j:
mov edx, 0 ; load 0 in i index
for_i:
cmp edx, ecx ; compare i with j
jge end_for_i ; if i >= j, end loop
inc DWORD PTR [comps] ; increment comparisons
mov eax, [esi + edx*4 + 4] ; load array[i + 1]
push eax ; pass as second argument
mov eax, [esi + edx*4] ; load array[i]
push eax ; pass as first argument
call Str_compare ; compare strings
jle for_i_next ; if array[i] <= array[i + 1], skip
inc DWORD PTR [swaps] ; increment swaps
; swap values array[i] and array[i + 1]
mov eax, [esi + edx*4 + 4] ; load array[i + 1]
mov ebx, [esi + edx*4] ; load array[i]
mov [esi + edx*4 + 4], ebx ; save swapped array[i + 1]
mov [esi + edx*4], eax ; save swapped array[i]
for_i_next:
inc edx ; i++
jmp for_i
end_for_i:
loop for_j ; j--, repeat while j>0
pop esi ; restore used registers
pop edx
pop ecx
pop ebx
pop ebp ; restore frame pointer
ret
PairBubbleSort ENDP
; Sorts an array using listwise bubble sort
; Prototype: ListBubbleSort(array, n)
ListBubbleSort PROC
push ebp ; save frame pointer
mov ebp, esp ; create new stack frame
push ebx ; save used registers
push ecx
push edx
push esi
mov DWORD PTR [swaps], 0 ; reset swap count
mov DWORD PTR [comps], 0 ; reset comparison count
mov esi, [ebp + 8] ; load array pointer
mov ecx, [ebp + 12] ; load array size n
dec ecx ; use n - 1
mov edi, 0 ; load 0 in index i
fori:
cmp edi, ecx ; compare i with j
jge end_fori ; if i >= n-1, end loop
mov [min], edi ; min = i
mov edx, edi ; j = i+1
inc edx
forj:
cmp edx, ecx ; compare j with n-1
jg end_forj ; if j > n-1, end loop
inc DWORD PTR [comps] ; increment comparisons
mov eax, [min]
mov eax, [esi + eax*4] ; load array[min]
push eax ; pass as second argument
mov eax, [esi + edx*4] ; load array[j]
push eax ; pass as first argument
call Str_compare ; compare strings
jge forj_next ; if array[j] >= array[min], skip
mov [min], edx ; min = j
forj_next:
inc edx ; j++
jmp forj
end_forj:
inc DWORD PTR [swaps] ; increment swaps
; swap values array[min] and array[i]
mov edx, [min]
mov eax, [esi + edx*4] ; load array[min]
mov ebx, [esi + edi*4] ; load array[i]
mov [esi + edx*4], ebx ; save swapped array[min]
mov [esi + edi*4], eax ; save swapped array[i]
inc edi ; i++
jmp fori
end_fori:
pop esi ; restore used registers
pop edx
pop ecx
pop ebx
pop ebp ; restore frame pointer
ret
ListBubbleSort ENDP
; Prints an array on the screen
; Prototype: PrintArray(array, n)
PrintArray PROC
push ebp ; save frame pointer
mov ebp, esp ; create new stack frame
push ecx ; save used registers
push esi
mov esi, [ebp + 8] ; load array pointer
mov ecx, [ebp + 12] ; load array size
print_loop:
mov edx, [esi] ; load string pointer from array
call WriteString ; generate a random string
cmp ecx, 1 ; if this is the last entry
je print_skip ; don't print separator
mov edx, OFFSET separator ; load address of separator string
call WriteString ; print separator on screen
print_skip:
add esi, 4 ; advance to next position
loop print_loop ; repeat for all entries
call CrLF ; jump to next line
call CrLF ; jump to next line
pop esi ; restore used registers
pop ecx
pop ebp ; restore frame pointer
ret
PrintArray ENDP
END main