【问题标题】:Segmentation faults in x86 NASM programx86 NASM 程序中的分段错误
【发布时间】: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


【解决方案1】:

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

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

【讨论】:

  • 在我的程序一开始我将 esi 归零,但之后它包含从文件中解析的数字数组。我在 '.printElement' 中使用 esi,它在那里工作正常
  • 另外,我在循环的每次迭代中都添加了 4,这只是将 edi 移动到数组的下一个元素的偏移量
  • esi 不会写入此程序中,除非被归零。如果还有其他代码,请说出来。至于i:它是一个标签,[esi+i]会使用标签的地址,而不是那里存储的值。
  • 哦,现在我明白了。你是完全正确的,我将不得不完全重组 '.diagonals' 的工作方式。感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 2012-06-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-11
  • 2015-03-31
相关资源
最近更新 更多