英文:
Having trouble finding the invalid memory access in my random number array sorting program
问题
在你的代码中,似乎有一些问题。不过你提到的具体错误信息是 "Access violation executing location 0x00000064",这通常表示访问了无效的内存位置。我会检查你的代码以寻找潜在的问题。
首先,我注意到在 sortList
过程中,你使用了寄存器 edx
,但没有在使用之前清除它的值。确保在使用 edx
之前将其清零。
另外,在 displayListDescending
过程中,你对 esi
进行了递减操作,但没有检查是否越界。请确保 esi
不会越界到数组之外。
最后,确保你的数组足够大来容纳 request
中指定的数量,否则可能会导致访问无效内存。
请检查这些问题,看看是否有助于解决你的异常问题。如果问题仍然存在,你可能需要更详细地调试以找到问题的确切位置。
英文:
I am coding this for an assignment, where I am required to make an array in MASM and assign it random numbers given a number input. I am past the selection sort part of my assignment, and I am having trouble finding out where I am not accessing the write memory. The error code that I get is:
> Exception thrown at 0x00000064 in Project.exe: 0xC0000005: Access violation executing location 0x00000064.
And here is the rest of my code:
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
My best guess where the exception is being thrown is in the displayListDescending procedure. I have tried to simplify the registers and have even tried to keep track of what ESI is even tracking.
I'd appreciate any help I possibly can get.
答案1
得分: 1
The exception
异常
我最好的猜测是异常被抛出的地方在 displayListDescending 过程中。
确实,在这里,您的程序在数组之外的内存中读取数据!计算数组中最后一个元素的偏移错误地将索引乘以4 重复两次。
mov ecx, [request] mov esi, OFFSET array mov eax, ecx dec eax mov ebx, 4 <<<< 1st x 4 mul ebx shl eax, 2 <<<< 2nd x 4 add esi, eax
解决方法之一是写成:
mov ecx, [request]
lea esi, [array + ecx * 4 - 4]
Random numbers
随机数
generateRandomNumbers PROC mov ecx, [request] mov esi, OFFSET array generateLoop: call RandomRange ; 在范围[0, 899]内生成随机数 add eax, 100 ; 调整范围为[100, 999] mov [esi], eax add esi, 4 loop generateLoop ret generateRandomNumbers ENDP
您没有在范围[0, 899]内生成随机数。要实现这一点,您需要在
call RandomRange
前将 ECX 设置为 900。但由于这会与当前的循环计数器冲突,您需要使用另一个寄存器来控制循环:
generateRandomNumbers PROC
mov edi, [request]
mov esi, OFFSET array
generateLoop:
mov ecx, 900
call RandomRange ; 在范围[0, 899]内生成随机数
add eax, 100 ; 调整范围为[100, 999]
mov [esi], eax
add esi, 4
dec edi
jnz generateLoop
ret
generateRandomNumbers ENDP
The median
中位数
mov edx, [medianValue] call WriteInt
传递给 WriteInt 的输入位于 EAX 中。
The selection sort
选择排序
sortList 及其附带的 exchangeElements 过程无法挽救。它们包含了许多难以解释的操作,这也使得很难确定它是否真正是选择排序,而不是其他排序方法。
我编写了这个选择排序算法,附带可视化演示,以便您了解它的工作原理。尽管它使用了16位寄存器,但将其移植到32位应该不难。
英文:
The exception
> My best guess where the exception is being thrown is in the displayListDescending procedure.
Indeed, that is where your program reads from memory outside of the array! The calculation of the offset to the last element in the array is erroneously multiplying the index by 4 doing it twice.
> mov ecx, [request]
> mov esi, OFFSET array
> mov eax, ecx
> dec eax
> mov ebx, 4 <<<< 1st x 4
> mul ebx
> shl eax, 2 <<<< 2nd x 4
> add esi, eax
One way to solve it is to write:
mov ecx, [request]
lea esi, [array + ecx * 4 - 4]
Random numbers
> 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
You are not generating a random number in the range [0,899]. For that to happen you need to set ECX=900 before call RandomRange
. But since that would clash with the current loop counter, you need to use another register to control the loop:
generateRandomNumbers PROC
mov edi, [request]
mov esi, OFFSET array
generateLoop:
mov ecx, 900
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
dec edi
jnz generateLoop
ret
generateRandomNumbers ENDP
The median
> mov edx, [medianValue]
> call WriteInt
The input to WriteInt goes in EAX.
The selection sort
The sortList and its accompanying exchangeElements procedures are not salvageable. They contain a lot of inexplicable operations that also make it hard to even find out if it is an actual selection sort and not some other sorting method.
I wrote this selection sort algorithm with a visual run-through so you can understand how it works. Although it uses 16-bit registers, porting it to 32-bit should not be difficult.
答案2
得分: 0
exchangeElements 可能需要一个 "ret 8",因为在调用它之前你压入了两个双字。
英文:
exchangeElements probably needs a "ret 8" since you push two dwords before calling it.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论