【发布时间】:2013-11-17 05:33:19
【问题描述】:
我有一个任务,我必须创建一个文本文件,例如:
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”标签中,直到那一点都有效。如果您将其注释掉,程序将恢复正常工作。
有人能说出导致问题的原因吗?
代码(有很多 cmets,所以如果您将其粘贴到自己的编辑器中可能会更容易理解):
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
【问题讨论】:
-
我不使用nasm,所以语法可能是正确的;但是当你按 n 时,你确定这会推动 &n(应该如此),而不是 n 中的值吗?
-
我想是的。在我添加“对角线”标签之前,所有程序所做的都是在从文件中将值解析为数组后输出数组。但它当时工作得很好,所以我认为它应该在那之后。
标签: loops assembly x86 segmentation-fault nasm