skylerWithAnE
skylerWithAnE

Reputation: 102

Segmentation Fault When Comparing a Value

I'm new to assembly and I've run into an issue that I do not know how to debug. I'm writing a very simple program that takes a command line argument and then prints the factors for the argument. The purpose is to become familiar with decisions and loops. I've managed to bolt it all together so far, and it works for even numbers but will not work for odd numbers. Additionally, it may produce correct results for even numbers, but it still runs into a segfault after the last check.

        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

Assembly is very difficult for me to wrap my mind around right now; I've got a lot to learn so I appreciate any feedback.

Upvotes: 0

Views: 372

Answers (1)

rkhb
rkhb

Reputation: 14409

The segmentation fault is caused by add esp,16. You push 6 dwords (= 24 bytes) onto the stack, so you have to clear the stack after the call printf with add esp,24.

Your code isn't compilable. This one works for me:

; 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

The "exit" with ret works only with GCC. If you use LD, you have to exit with a syscall (int 80h/ fn 01h).

Upvotes: 1

Related Questions