Reputation: 102
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
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