使用选择排序排序的随机数数组 - 大小 > 130 的垃圾字符输出
Random number array sorted with Selection Sort -- garbage characters output for size > 130
我的程序接受用户输入(10 到 200 之间的整数)并打印出输入的随机数并将它们存储在一个数组中。然后数组被排序并打印出来(见下图)。数字的中位数也打印在屏幕上。
我没能找到错误。该程序完美适用于小于或等于 130 但不超过 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
下面是我的输出目前的样子
下面是我希望输出的样子:
我将继续把我的评论变成一个答案,这样我们就可以结束这个问题了。
我相信 OP 遇到的问题来自这段代码:
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
如您所见,ecx 从 [ebp+8]
加载。这是存储有关条目数的用户输入的位置。然后代码遍历位于 edi 的生成的随机数数组。
第一次执行此代码时,ebx 从 0 开始。因此它安全地遍历列表中的(比方说)200 个条目。
然而,在随后的遍历中,ebx 可以大于 0。但是,ecx 仍然是 200。所以我们仍然要遍历 200 个条目,但我们不再从索引零开始。
这意味着,我们 reading/writing 已超过分配的 space。这就是为什么输出是垃圾的原因。
这似乎适用于较少条目的原因是列表的 space 是 pre-allocated(显然是零填充?)。由于排序是 'descending,',所有零看起来都不需要移动。
虽然我还没有追查到所有的来龙去脉,但至少这将是一个问题。
在 mov ecx, [ebp+8]
之后添加 sub ecx, ebx
的简单修复似乎可以解决问题。
我的程序接受用户输入(10 到 200 之间的整数)并打印出输入的随机数并将它们存储在一个数组中。然后数组被排序并打印出来(见下图)。数字的中位数也打印在屏幕上。
我没能找到错误。该程序完美适用于小于或等于 130 但不超过 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
下面是我的输出目前的样子
下面是我希望输出的样子:
我将继续把我的评论变成一个答案,这样我们就可以结束这个问题了。
我相信 OP 遇到的问题来自这段代码:
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
如您所见,ecx 从 [ebp+8]
加载。这是存储有关条目数的用户输入的位置。然后代码遍历位于 edi 的生成的随机数数组。
第一次执行此代码时,ebx 从 0 开始。因此它安全地遍历列表中的(比方说)200 个条目。
然而,在随后的遍历中,ebx 可以大于 0。但是,ecx 仍然是 200。所以我们仍然要遍历 200 个条目,但我们不再从索引零开始。
这意味着,我们 reading/writing 已超过分配的 space。这就是为什么输出是垃圾的原因。
这似乎适用于较少条目的原因是列表的 space 是 pre-allocated(显然是零填充?)。由于排序是 'descending,',所有零看起来都不需要移动。
虽然我还没有追查到所有的来龙去脉,但至少这将是一个问题。
在 mov ecx, [ebp+8]
之后添加 sub ecx, ebx
的简单修复似乎可以解决问题。