Search code examples
sortingassemblymasm

having trouble debugging assembly program to sort dates


I have been working on an assembly program that sorts a list of dates and then prints out the dates sorted oldest to newest. The dates are in the format of DD- MMM-YYYY, e.g. “23-JUL-2010”.

I have made steady progress, but now my program crashes right away, and I'm having difficulty finding out why. I'm using the MASM32 editor.

Here's my program...

include \masm32\include\masm32rt.inc

.data?
number dd ?
.data

dates BYTE "23-JUL-2010", 0, "22-JUL-2010", 0, "23-JUL-2009", 0, "31-JUL-2012", 0, "05-MAR-2010", 0, "12-MAR-1010", 0
values dd 5 DUP(0, 0, 0, 0, 0)
nDates DWORD 6
counter DD 0
temp dd 0
years dd 0
months BYTE "JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC",0

.code

DateToNumber MACRO items, mons, result
    LOCAL loop_top
    PUSHAD

    lea EDI, [items]
    MOV AL, [EDI]
    AAA
    MOV BL, 10
    MUL BL
    MOV DL, AL
    ADD EDI, 1
    SUB EAX, EAX
    MOV AL, [EDI]
    AAA
    ADD DL, AL
    MOV result, EDX
    SUB EDX, EDX
    SUB ESI, ESI
    SUB EDI, EDI
    mov EAX, 0          ; EAX is the month number

    loop_top:
         lea ESI, [items+3] ; ESI will be a ptr into the date string we are trying to convert to a number
         lea EDI, [mons + EAX * 4]   ; EDI will be a ptr into the months array

         inc EAX
         mov ECX, 3          ; length of a month string
         cld
         repe cmpsb          ; compare mystring and months for 3 characters

         jne loop_top        ; keep looping until we find the month

    mov EBX, result
    mov BH,AL
    SUB EBX, EBX
    MOV years, EBX  
    lea EDI, [items]
    ADD EDI,7
    MOV AL, [EDI]
    AAA
    MOV BX, 1000
    MUL BX
    MOV years, EAX
    SUB BX, BX
    SUB EAX, EAX
    ADD EDI, 1
    MOV AL, [EDI]
    AAA
    MOV BX, 100
    MUL BX
    SUB BX, BX
    ADD years, EAX
    SUB EAX, EAX
    ADD EDI, 1
    MOV AL, [EDI]
    AAA
    MOV BX, 10
    MUL BX
    SUB BX, BX
    ADD years, EAX
    SUB EAX, EAX
    ADD EDI, 1
    MOV AL, [EDI]
    AAA
    SHL EAX, 16
    ADD result, EAX
    POPAD
ENDM


start:
    MOV ECX, 1
    SUB EDX, EDX
    SUB EAX, EAX
    DateToNumber dates, months, number
    MOV EAX, number
    MOV values, EAX
    DateToNumber [dates+12], months, number
    MOV EAX, number

    MOV [values+4], EAX
    DateToNumber [dates+24], months, number
    MOV EAX, number
    MOV [values+8], EAX
    DateToNumber [dates+48], months, number
    MOV EAX, number
    MOV [values+16], EAX
    DateToNumber [dates+36], months, number
    MOV EAX, number
    MOV [values+12], EAX
    DateToNumber [dates+60], months, number
    MOV EAX, number
    MOV [values+20], EAX
    print chr$("[ ",)

    ;lea EDI, [values]
    ;push EDI
    ;Call BubbleSort

    ;Call NumberToDate
out_top:

    mov eax, [values+esi*4]
    mov temp, eax
    print str$(temp)
    print chr$(", ")
    inc esi
    cmp esi, 5
    jne out_top

    ; Formatting the last character
    mov eax, [values+esi*4]
    mov temp, eax
    print str$(temp)
    print chr$(" ]", 13, 10)
exit

;NumberToDate-
;   Parameter is a 32-bit unsigned number.
;   Turns the number back into its corresponding date string.
;   Returns the address of the string.
;
NumberToDate :

    enter 0, 0

    print "NumberToDate called"
    leave
    ret 0

;BubbleSort-
;   Parameters are the address of an array of 32-bit unsigned numbers and the length of the array.
;   Sorts the array in place from smallest to largest.
;   No return value.
;
BubbleSort:

    enter 0, 0
    PUSHAD
    mov ecx, 0
    mov edx, 0
    print "BubbleSort called"

    MOV ESI, [EBP + 8]

    top:
        cmp edx, 5
        je inc_loop
        inc edx           
        mov eax, [esi+ecx*4] ; moves array index 0 into eax

        cmp [esi+edx*4], eax ; compares index 1 to index 2
        jl top             ; jumps to top if index1 is less than or equal to index 2

        ; swaps the values edx and ecx are pointing to
        mov ebx, [esi+edx*4]
        mov [esi+ecx*4], ebx
        mov [esi+edx*4], eax
        jmp top

    inc_loop:
        mov edx, -1
        inc ecx
        cmp ecx, 5
        jl top

    POPAD
    leave
    ret 4  

END start

If any of you could help me understand where I'm going wrong, or help me debug this I would greatly appreciate it. Thanks in advance!


Solution

  • out_top:
        mov eax, [values+esi*4]
        mov temp, eax
        print str$(temp)
        print chr$(", ")
        inc esi
        cmp esi, 5
        jne out_top
    

    In this part of your program you depend on the correct value in ESI, but you forgot to initialize it!

        XOR ESI, ESI        <<<< Add this line
    out_top:
        mov eax, [values+esi*4]
        mov temp, eax
        print str$(temp)
        print chr$(", ")
        inc esi
        cmp esi, 5
        jne out_top
    

    values dd 5 DUP(0, 0, 0, 0, 0)
    

    Seeing this I suspect you don't understand the DUP operator very well!
    Your code needs to reserve space for 6 dwords, but this line reserves 25 such dwords. Write one of the following:

    values dd 0,0,0,0,0,0
    

    or else

    values dd 6 dup(0)
    

    Having your DateToNumber code as a macro wastes a lot of bytes. This should have been written as a subroutine.
    Remember that each time you use the macro, the entire code snippet is substituted. In your program this happens 6 times.