My program takes user input (integer between 10 and 200) and prints out the entered number of random numbers and stores them in an array. Then the array is sorted and printed out (SEE IMAGE BELOW). The median is of the numbers are also printed on the screen.
I have not been able to find the error. The program works perfectly for numbers less than or equal to 130, but not over 130.
TITLE Program5 (Program5.asm)
INCLUDE Irvine32.inc
; (insert constant definitions here)
MIN_INPUT = 10
MAX_INPUT = 200
LO_RANDOM = 100
HI_RANDOM = 999
.data
request DWORD 10
ask_user BYTE "How many numbers should be generated? [10 ... 200]: ", 0
error BYTE "Invalid input", 0
title_1 BYTE "The unsorted random numbers: ", 0
title_2 BYTE "The sorted list: ", 0
space BYTE " ", 0
median BYTE "The median is: ", 0
temp DWORD 0
list DWORD MAX_INPUT DUP(?)
.code
main PROC
; (insert executable instructions here)
call randomize
push OFFSET request ;passed by reference
call getData
call CrLf
push request ; passed by value
push OFFSET list ; passed by reference
call fillArray
push OFFSET list
push request
push OFFSET title_1
call displaylist
push OFFSET list
push request
call sortList
push OFFSET list
push request
call displayMedian
call CrLf
call CrLf
push OFFSET list
push request
push OFFSET title_2
call displaylist
exit ; exit to operating system
main ENDP
; (insert additional procedures here)
getData PROC
push ebp ;Set up stack frame
mov ebp, esp
;get an integer from user
mov ebx, [ebp+8] ;get address of request into ebx
L1:
mov edx, OFFSET ask_user
call WriteString
call ReadDec
cmp eax, MIN_INPUT
jl errorMessage
cmp eax, MAX_INPUT
jg errorMessage
cmp eax, MIN_INPUT
jge endThis
cmp eax, MAX_INPUT
jle endThis
errorMessage:
mov edx, OFFSET error
call WriteString
call CrLf
jmp L1
endThis:
mov [ebx], eax
pop ebp
ret 4 ; remove four more bytes from the stack (after ret @)
getData ENDP
fillArray PROC
;include parameters - request (value), array (reference)
; MAJORITY OF THE FOLLOWING CODE WAS EXTRACTED FROM LECTURE 20 SLIDES
push ebp
mov ebp, esp ;[ebp+4]
mov edi, [ebp+8] ; @list in edi
mov ecx, [ebp+12] ; value of request in ecx
more:
mov eax, HI_RANDOM
sub eax, LO_RANDOM
inc eax
call RandomRange
add eax, LO_RANDOM
mov [edi], eax
add edi, 4
loop more
endmore:
pop ebp
ret 8
fillArray ENDP
sortList PROC
push ebp
mov ebp, esp
mov edi, [ebp+12]
mov ecx, [ebp+8]
dec ecx
mov ebx, 0
firstLoop:
mov eax, ebx
mov edx, ebx
inc edx
push ecx
mov ecx, [ebp+8]
secondLoop:
mov esi, [edi + (edx * 4)]
cmp esi, [edi + (eax * 4)]
jle lesser
mov eax, edx
lesser:
inc edx
loop secondLoop
push edx
push esi
push [edi + (ebx * 4)] ; array[k]
push [edi + (eax * 4)] ; array[i]
call exchangeElements
pop [edi + (eax * 4)]
pop [edi + (ebx * 4)]
pop esi
pop edx
pop ecx ; set the
inc ebx ; increment k in the first loop
loop firstLoop
pop ebp
ret 8
sortList ENDP
exchangeElements PROC
push ebp
mov ebp, esp
mov esi, [ebp+12] ; array[k]
mov edx, [ebp+8] ; array[i]
mov [ebp+8], esi
mov [ebp+12], edx
pop ebp
ret
exchangeElements ENDP
displayMedian PROC
push ebp
mov ebp, esp ;[ebp+4]
mov edi, [ebp+12] ; @list in edi
mov ecx, [ebp+8] ; value of request in ecx
mov eax, ecx
mov ebx, 2
cdq
div ebx
cmp edx, 0
je isEven
cmp edx, 1
je isOdd
; https://github.com/TRMassey/CS271/blob/master/assignment5.asm
isEven:
; find the higher number
mov ebx, 4
mul ebx
add edi, eax
mov edx, [edi]
; find the lower number
mov eax, edi
sub eax, 4
mov edi, eax
mov eax, [edi]
; add and divide them by 2
add eax, edx
mov edx, 0
mov ebx, 2
cdq
div ebx
; print out the median value (rounded to the nearest int)
call CrLf
call CrLf
mov edx, OFFSET median
call WriteString
call WriteDec
jmp finish
isOdd:
mov eax, [edi + (eax * 4)]
call CrLf
call CrLf
mov edx, OFFSET median
call WriteString
call WriteDec
jmp finish
finish:
pop ebp
ret
displayMedian ENDP
displayList PROC
push ebp
mov ebp, esp ; [ebp+4]
mov ecx, [ebp+12] ; @request
mov edi, [ebp+16] ; @list
mov esi, 10
mov edx, [ebp+8] ; @title
call WriteString
call CrLf
show:
mov eax, [edi]
call WriteDec
mov edx, OFFSET space
call WriteString
add edi, 4
dec esi
cmp esi, 0
je callClear
loopAgain:
loop show
jmp endshow
callClear:
mov esi, 10
call CrLf
jmp loopAgain
endshow:
pop ebp
ret 12
displayList ENDP
END main
I'm going to go ahead and turn my comments into an Answer so we can close this question.
I believe the problem OP is experiencing comes from this code:
As you can see, ecx gets loaded from
[ebp+8]
. This is where the user input regarding the number of entries is stored. The code then walks over the array of generated random numbers located at edi.The very first time this code is executed, ebx starts at 0. So it safely walks the (say) 200 entries in the list.
However, on subsequent passes, ebx can be larger than 0. But, ecx is still 200. So we're still going to walk 200 entries, but we are no longer starting at index zero.
Which means, we're reading/writing past the end of the allocated space. Which is why the output is junk.
The reason this seems to work for smaller numbers of entries is that the space for the list is pre-allocated (and apparently zero filled?). Since the sort is 'descending,' the zeros all look like they don't need to be moved.
While I haven't traced thru all the ins and outs of the sort, at a minimum this is going to be a problem.
A simple fix of adding
sub ecx, ebx
right aftermov ecx, [ebp+8]
seems to resolve the problem.