Hello again, NASM Forums. It's been a while.
So I am trying to use bubble sort to sort an array (table). I have it go along and it does a decent job doing the for loop structures ( I think ). I'm not sure the correct values are reaching the registers ( and when I get home, I will be able to test that. I don't have enough time right now ).
I copied the relevant bits of code into a separate source file to test just the sort function. Here it is:
section .data
table dw 23,100,3,22,4,6
tLen dw 6
section .bss
index_k resd 1
index_i resd 1
isSorted resd 1
section .text
;;; These are macros I use to simplify subroutine creation.
;;; They are required to be definied before their use.
%macro prologue 0
push ebp
mov ebp, esp
%endmacro
%macro epilogue 0
mov esp, ebp
pop ebp
%endmacro
%macro pushregs 0
push eax
push ebx
push ecx
push edx
%endmacro
%macro popregs 0
pop edx
pop ecx
pop ebx
pop eax
%endmacro
global _start
_start:
main:
;; prints unsorted table first
call printtbl
;; sorts table here
call sorttbl
call write_newline
;; prints newly sorted table here
call printtbl
;; sys_exit(0)
xor ebx, ebx
mov eax, ebx
inc eax
int 0x80
;;;;;;;;;;;;;;;;;
;;; sorttbl ;;;
;;;;;;;;;;;;;;;;;
;;; Function for sorting the table
sorttbl:
prologue
pushregs
.logic:
;; public static void bubbleSort(int[] data)
;;{
;;for (int k = 0; k < data.length - 1; k++)
;; {
;; boolean isSorted = true;
;;
;; for (int i = 1; i < data.length - k; i++)
;; {
;; if (data[i] < data[i - 1])
;; {
;; int tempVariable = data[i];
;; data[i] = data[i - 1];
;; data[i - 1] = tempVariable;
;;
;; isSorted = false;
;;
;; }
;; }
;;
;; if (isSorted)
;; break;
;; }
;; }
.for1_init:
xor ecx, ecx
mov [index_k], ecx
.for1_logic:
; isSorted = true
xor ecx, ecx
inc ecx
mov [isSorted], ecx
; is k < len?
mov eax, [index_k]
mov ebx, [tLen]
cmp eax, ebx
jge .done
.for2_init:
xor ecx, ecx
inc ecx
mov [index_i], ecx
.for2_logic:
; if table[i] < table[i+1]
mov ecx, [index_i]
lea eax, [table + 4 * ecx]
lea ebx, [table + 4 * (ecx - 1)]
mov eax, [eax]
mov ebx, [ebx]
cmp eax, ebx
jge .for2_exit
.for2_swap:
lea eax, [table + 4 * ecx]
lea ebx, [table + 4 * (ecx - 1)]
mov ecx, [eax]
xchg [ebx], ecx
mov [eax], ecx
; isSorted = false
mov [isSorted], ecx
.for2_exit:
mov ecx, [index_i]
inc ecx
mov [index_i], ecx
mov ebx, [tLen]
sub ebx, [index_k]
cmp ecx, ebx
jl .for2_logic
.for1_swapcheck:
mov eax, [isSorted]
xor ebx, ebx
cmp eax, ebx
jne .done
.for1_exit:
mov ecx, [index_k]
inc ecx
mov [index_k], ecx
jmp .for1_logic
.done:
; finished
popregs
epilogue
ret
;;; END SORTTBL FUNCTION
;;;;;;;;;;;;;;;;;;
;;; printtbl ;;;
;;;;;;;;;;;;;;;;;;
;;; The printtbl subroutine prints out the contents of the array
;;; i.e., steps 6 and 9
;;; ARG1: address of array, ARG2: length of array
printtbl:
prologue
pushregs
.setup:
xor ecx, ecx
.prnt_loop:
;; Put the appropriate number from the table into ebx.
;; Then, call the writei function to output it to the
;; terminal. Then, call the write_newline function to
;; write a newline to the screen.
lea ebx, [table+ecx*2]
movzx ebx, word [ebx]
push ebx
call writei
add esp, 4
call write_newline
inc ecx
;; Now compare ecx to the length of the table to see
;; if we still have more numbers to print
mov ebx, [tLen]
cmp ecx, ebx
jb .prnt_loop
.done:
popregs
epilogue
ret
;;; END PRNTTBL FUNCTION
;;;;;;;;;;;;;;;;
;;; writei ;;;
;;;;;;;;;;;;;;;;
;;; Function for writing an integer value to the screen
;;; ARG1: actual integer to print
writei:
prologue
pushregs
.setup:
;; We load the value to convert into eax. Then we put
;; 10 into ebx for the decimal conversion and clear
;; ecx to use for counting
mov eax, [ebp+8]
mov ebx, 10
xor ecx, ecx
.divide:
;; Divide by ten until there is nothing left in eax
xor edx, edx
div ebx
push edx
inc ecx
cmp eax, 0
jne .divide
.writedigits:
;; Now we take off each digit one
;; at a time, add '0' to each digit,
;; push the new integer to the stack,
;; point the write call to the top
;; of the stack.
pop eax
add eax, 0x30
;; Save register for count
push ecx
;; push eax to write
push eax
;; Write
mov edx, 1
mov ecx, esp
mov ebx, 1
mov eax, 4
int 0x80
;; throwaway esp value
add esp, 4
;; retrieve count
pop ecx
;; Decrement the counter and if
;; it isn't zero, write another
;; digit.
dec ecx
cmp ecx, 0
jg .writedigits
.done:
popregs
epilogue
ret
;;; END WRITEi FUNCTION
;;;;;;;;;;;;;;;;;;;;;;;
;;; write_newline ;;;
;;;;;;;;;;;;;;;;;;;;;;;
;;; subroutine for printing a newline to screen
write_newline:
pushregs
.printing:
;; We have to push the newline char to the stack for
;; printing it.
mov edx, 1
push 0x0a
mov ecx, esp
mov ebx, 1
mov eax, 4
int 0x80
add esp, 4
.done:
popregs
ret
;;; END WRITE_NEWLINE FUNCTION
I'm just wondering if there are any glaring mistakes in there that I cannot see.
Compile code:
nasm -g -f elf32 sort-sample.asm
ld -melf_i386 sort-sample.o -o out
Thanks for your time!
Regards,
Nick