我正在编写一个赋值代码,我需要在MASM中创建一个数组,并在给定数字输入的情况下为其分配随机数。我已经过了作业的选择排序部分,而且我很难找到我没有访问写内存的位置。我得到的错误代码是:
在Project.exe中的0x00000064处引发异常:0xC0000005:访问冲突执行位置0x00000064。
下面是我的代码的其余部分:
INCLUDE Irvine32.inc
.data
instructions BYTE "This program generates random numbers in the range [100 .. 999], displays the original list, sorts the list, and calculates the median value. Finally, it displays the list sorted in descending order.",0
unsorted BYTE "The unsorted random numbers:",0
median BYTE "The median is ",0
sorted BYTE "The sorted list:",0
prompt BYTE "How many numbers should be generated? [10 .. 200]: ",0
invalid BYTE "Invalid input",0
newline BYTE 0DH, 0AH, 0
spaceBar BYTE " ", 0
array DWORD 200 DUP(?)
request DWORD ?
medianValue DWORD ?
.code
main PROC
call introduction
call getData
call generateRandomNumbers
call displayList
call calculateMedian
call displayMedian
call sortList
call displayListDescending
exit
main ENDP
introduction PROC
mov edx, OFFSET instructions
call WriteString
call Crlf
ret
introduction ENDP
getData PROC
mov edx, OFFSET prompt
call WriteString
call ReadInt
cmp eax, 10
jl invalidInput
cmp eax, 200
jg invalidInput
mov [request], eax
ret
invalidInput:
mov edx, OFFSET invalid
call WriteString
call Crlf
jmp getData
getData ENDP
generateRandomNumbers PROC
mov ecx, [request]
mov esi, OFFSET array
generateLoop:
call RandomRange ; Generates random number in the range [0, 899]
add eax, 100 ; Adjust the range to [100, 999]
mov [esi], eax
add esi, 4
loop generateLoop
ret
generateRandomNumbers ENDP
displayList PROC
mov edx, OFFSET unsorted
call WriteString
call Crlf
mov edx, OFFSET newline
call WriteString
mov ecx, [request]
mov esi, OFFSET array
displayLoop:
mov eax, [esi]
call WriteInt
mov edx, OFFSET spaceBar
call WriteString
add esi, 4
loop displayLoop
call Crlf
ret
displayList ENDP
calculateMedian PROC
mov ecx, [request]
shr ecx, 1
mov esi, OFFSET array
mov eax, [esi+ecx*4]
mov [medianValue], eax
ret
calculateMedian ENDP
displayMedian PROC
mov edx, OFFSET median
call WriteString
call Crlf
mov edx, OFFSET newline
call WriteString
mov edx, [medianValue]
call WriteInt
call Crlf
ret
displayMedian ENDP
sortList PROC
mov ecx, [request]
mov esi, OFFSET array
mov ebx, OFFSET array
mov edi, ecx
sortLoop:
xor edx, edx
mov eax, [esi]
innerLoop:
add ebx, 4
cmp ebx, edi
jge skipExchange
mov edx, [ebx]
cmp edx, 100
jge skipExchange
mov eax, edx
mov edi, ebx
skipExchange:
loop innerLoop
cmp esi, edi
je skipSwap
push eax
push [esi]
call exchangeElements
skipSwap:
add esi, 4
cmp edx, 0
jne sortLoop
ret
sortList ENDP
displayListDescending PROC
mov edx, OFFSET newline
call WriteString
mov ecx, [request]
mov esi, OFFSET array
mov eax, ecx ; Store the value of ecx in eax
dec eax ; Decrement eax to get (ecx-1)
mov ebx, 4
mul ebx
shl eax, 2 ; Multiply by 4 (shift left by 2)
add esi, eax ; Add the offset to the base address of the array
displayLoop:
mov eax, [esi]
call WriteInt
mov edx, OFFSET spaceBar
call WriteString
sub esi, 4
loop displayLoop
call Crlf
ret
displayListDescending ENDP
exchangeElements PROC
push edx
mov edx, [esp+12]
mov ecx, [esp+8]
mov [esp+12], ecx
mov [esp+8], edx
pop edx
ret
exchangeElements ENDP
END main
我最好的猜测是在 displayListDescending 过程中抛出异常。我试着简化寄存器,甚至试着跟踪ESI正在跟踪的内容。
我会很感激任何我能得到的帮助。
2条答案
按热度按时间w3nuxt5m1#
异常
我最好的猜测是在 displayListDescending 过程中抛出异常。
事实上,这就是你的程序从数组之外的内存中读取的地方!数组中最后一个元素的偏移量的计算错误地将索引乘以4**,这样做了两次**。
解决这个问题的一种方法是写:
随机数
您没有生成范围[0,899]内的随机数。为此,您需要在
call RandomRange
之前设置ECX=900。但由于这会与当前循环计数器冲突,因此需要使用另一个寄存器来控制循环:中位数
选区排序
我写了一个可视化的selection sort algorithm,这样你就可以理解它是如何工作的。虽然它使用16位寄存器,但将其移植到32位应该不难。
d5vmydt92#
exchangeElements可能需要一个“ret 8”,因为你在调用它之前推了两个dword。