Loops x86 NASM程序中的分段错误
我有一个任务,必须创建一个文本文件,例如:Loops x86 NASM程序中的分段错误,loops,assembly,x86,segmentation-fault,nasm,Loops,Assembly,X86,Segmentation Fault,Nasm,我有一个任务,必须创建一个文本文件,例如: 4 5 3 6 7 8 2 3 1 8 9 6 3 4 2 1 9 其中“4”定义了行/列的数量,并在NASM中编写了一个程序来查找对角线数字的总和,因此在本例中: 5 + 2 + 6 + 3 很明显,它会返回总数,22 我很确定我已经准备好了。我获取文件的输入,并使用文件中的第一个数字来定义文件的尺寸。因此,如果第一个数字是4,则文件的维度是4^2+1(1表示第一个数字)。n^2+1也是执行下一段的循环的退出条件: 此时,我使用fscanf()逐
4
5 3 6 7
8 2 3 1
8 9 6 3
4 2 1 9
其中“4”定义了行/列的数量,并在NASM中编写了一个程序来查找对角线数字的总和,因此在本例中:
5 + 2 + 6 + 3
很明显,它会返回总数,22
我很确定我已经准备好了。我获取文件的输入,并使用文件中的第一个数字来定义文件的尺寸。因此,如果第一个数字是4,则文件的维度是4^2+1(1表示第一个数字)。n^2+1也是执行下一段的循环的退出条件:
此时,我使用fscanf()逐个遍历文件并将其添加到数组中。在此之后,我需要做的就是获取数组的每个n+1元素(在本例中,n=4),直到到达数组的末尾,然后将它们全部相加
最后一段都发生在底部的“.diagonals”标签中,在这一点之前,一切都正常。如果你把它注释掉,程序就会恢复正常工作
有人能说出是什么引起了问题吗
代码(有很多注释,因此如果您将其粘贴到自己的编辑器中,可能会更容易理解):
您可以将esi设置为零,并且从不更改它<代码>mov eax、[esi+ecx]将因此访问无效内存
代码在其他方面是可疑的:
mov[esi+i],考虑到i
是单个dword,edi
如何合理?我不使用nasm,因此语法可能是正确的;但是当你推n时,你确定这推了&n(应该是这样),而不是n的值吗?我想是的。在我添加“对角线”标签之前,程序所做的全部工作是在从文件中解析值后输出数组。但它当时工作得很好,所以我认为应该是在那一点之后。在我的程序的一开始,我将esi设为零,但后来它包含了从文件解析的数字数组。我在“.printElement”中使用esi,它在那里工作得很好。在循环的每次迭代中,我都会向它添加4个元素,它只是一个偏移量,用于将edi移动到数组的下一个元素。esi
在这个程序中没有写入,除了归零。如果有其他代码,请说明。至于i
:它是一个标签,[esi+i]
将使用标签的地址,而不是存储在那里的值。哦,现在我看到了。你完全正确,我将不得不完全重组“.对角线”的工作方式。谢谢你的帮助。
extern fopen
extern fclose
extern fscanf
extern printf
global main
SEGMENT .data
n: DD 0
i: DD 0
x: DD 0 ; variable for first digit of the file, which determines the number of rows/columns in the file
loopCounter: DD 0 ; will be set to (n-1) where n is the first number in the file
sum1: DD 0
sum2: DD 0
format: DD "%d",0
formatInt: DD "%d ",0
readmode: DD "r", 0
filename: DD "hw5_2.dat", 0
SEGMENT .text
main:
push readmode ; push "r"
push filename ; filehandle
call fopen ; open file, returns pointer to file in eax
add esp, 8 ; balance stack
xor esi, esi ; clear esi
xor ecx, ecx ; clear ecx
mov ebx, eax ; move pointer to file to ebx
jmp .fileCycle
.firstLoop: ; this is the first time the loop has run so it must determine the first value to use for the number of rows/columns
xor eax, eax ; clear eax, just in case
mov eax, edi ; move first number from file into eax
mov [loopCounter], eax ; loopCounter = 4
sub [loopCounter], dword 1
;mov [x], edi ; move it also into [x], may need it later
mul eax ; eax = eax*eax
mov edx, eax ; move result to edx
mov [x], eax ; also move result to [x]
add [x], dword 4 ; add 4 to [x], this will become the offset later when adding the diagonals together
inc eax ; number of elements is n^2 + 1, so eax must be incremented
inc ecx ; increment loop counter, as this method runs before it can happen in the loop
jmp .fileCycle ; resume loop, this method will not run again
.fileCycle: ; this method cycles through the file and adds all the elements one by one into the esi register
cmp ecx, eax ; end of file?
;je .finished
je .diagonals ; YES - time to find diagonals
push eax
push ebx
push ecx
push edx
push n ; store scanned value in n
push format ; store as int
push ebx ; get input from file pointed to by eax
call fscanf
add esp, 12 ; balance stack
mov edi, [n] ; move value at n into edi
mov [esi+i], edi ; store values in file as an array of ints located at esi
.printElement:
push dword [esi+i] ; pass current element of array by value
push formatInt ; pass format argument
call printf ; print current element
add esp, 8 ; balance stack
pop edx
pop ecx
pop ebx
pop eax
add [i], dword 4 ; increment array index
cmp ecx, dword 0 ; is this the first time going through the loop?
je .firstLoop ; YES - firstLoop method must be run
inc ecx ; inc loop counter
jmp .fileCycle ; NO - keep looping
.diagonals: ; calculate the first diagonal sum
xor eax, eax ; clear certain registers to be reused
xor ecx, ecx
xor edi, edi
mov ecx, dword 4 ; start the counter at 4 so it grabs the 2nd number of the array first
.L1:
cmp edi, [loopCounter] ; compare edi (local loop counter) to loopCounter (the number of diagonals to add)
je .finished ; counters are equal - program finished
mov eax, [esi+ecx] ; move next diagonal element into eax
add [sum1], eax ; add it to the sum
add ecx, [x] ; ecx += 20, 20 in this case is the dword offset to get the next diagonal
inc edi ; inc loop counter
.finished:
push ebx
call fclose ; close the file
add esp, 4
ret