x86 NASM程序中的分段错误

时间:2013-11-17 05:33:19

标签: 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()逐个浏览文件并将其添加到数组中。在此之后,我需要做的是获取数组的每个n + 1个元素(在这种情况下n = 4),直到到达数组的末尾并将它们全部加在一起。

最后一段都发生在'.diagonals'标签的底部,直到那一刻都有效。如果你要对它进行评论,程序将恢复正常工作。

有人可以告诉那些导致问题的是什么吗?

代码(有很多评论,所以如果你把它粘贴在你自己的编辑器中可能会更容易理解):

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

1 个答案:

答案 0 :(得分:0)

你归零esi并且永远不会改变它。因此mov eax, [esi+ecx]将访问无效内存。

代码在其他方面存在疑问:考虑到mov [esi+i], edi是单个双字,i如何合理?