比较值时的分段错误

时间:2014-08-29 06:05:10

标签: assembly x86 segmentation-fault nasm 32-bit

我是装配新手,我遇到了一个我不知道如何调试的问题。我正在编写一个非常简单的程序,该程序接受命令行参数,然后打印参数的因子。目的是熟悉决策和循环。到目前为止,我设法将它们全部组合在一起,它适用于偶数,但不适用于奇数。此外,它可能会为偶数产生正确的结果,但在最后一次检查后仍然会遇到段错误。

        section .bss
        input: resb 100
        count: resb 100


        main:
                mov ecx,[esp+8]             ;point to command line arguement
                mov eax,[ecx+4]             ;extract second element 


                push dword eax              ;segfaults without dword. 
                call atoi                   ;convert the ascii from cmd line into integer.
                add esp,4
                mov dword [input],eax       ;copy original

                xor edx, edx                ;zero out edx to prevent division error. [2]
                mov ebx,2
                div ebx                     ;divide eax by ebx. quotient stored in eax, remainder stored in edx. 

                mov [count],eax             ;make a copy of the original argument/2, no number larger can be a factor.

                jmp checkAgain

        ret

        ;strFormat db `Count: %d, Quotient: %d, Remainder: %d, Input: %d, EBX: %d\n`,0

        true:
                push ebx
                push dword [input]
                push edx
                push eax
                push dword [count]

                push strFormat
                call printf
                add esp,16
                cmp dword [count],0
                jg checkAgain
        ret

        checkAgain:

                xor edx,edx
                mov eax,[input]
                mov ebx,[count]
                div ebx
                dec dword [count]
                cmp edx,0
                je true
                mov ecx,dword [count]    
                cmp ecx,0               ;this is where I expect the program to end, but it crashes.
                jg checkAgain
        ret

我现在非常难以集思广益;我有很多东西需要学习,所以我很感激任何反馈。

1 个答案:

答案 0 :(得分:1)

分段错误是由add esp,16引起的。您将6个双字(= 24个字节)压入堆栈,因此必须在call printf之后用add esp,24清除堆栈。

您的代码无法编译。这个对我有用:

; Name:     spagfac.asm
; Assemble: nasm -felf32 spagfac.asm
; Link:     gcc -m32 -o spagfac spagfac.o
; Run:      ./spagfac 60

global main
extern atoi, printf

section .bss
    input: resb 100
    count: resb 100

section .data
    strFormat db `Count: %d, Quotient: %d, Remainder: %d, Input: %d, EBX: %d\n`,0

section .text

    main:
        mov ecx,[esp+8]         ;point to command line arguement
        mov eax,[ecx+4]         ;extract second element


        push dword eax          ;segfaults without dword.
        call atoi               ;convert the ascii from cmd line into integer.
        add esp,4
        mov dword [input],eax   ;copy original

        xor edx, edx            ;zero out edx to prevent division error. [2]
        mov ebx,2
        div ebx                 ;divide eax by ebx. quotient stored in eax, remainder stored in edx.

        mov [count],eax         ;make a copy of the original argument/2, no number larger can be a factor.

        jmp checkAgain

    ret

    true:
        push ebx
        push dword [input]
        push edx
        push eax
        push dword [count]

        push strFormat
        call printf
        add esp,24
        cmp dword [count],0
        jg checkAgain
    ret

    checkAgain:

        xor edx,edx
        mov eax,[input]
        mov ebx,[count]
        div ebx
        dec dword [count]
        cmp edx,0
        je true
        mov ecx,dword [count]
        cmp ecx,0
        jg checkAgain
    ret

"退出" ret仅适用于GCC。如果使用LD,则必须使用系统调用(int 80h / fn 01h)退出。