Click to See Complete Forum and Search --> : x86 ASM segfaults...


Minime80
02-13-2002, 04:43 AM
Okay, this assembly stuff is really getting on my nerves. I just don't thing I'm getting it. This program is supposed to go through and display some numbers to the screen digit by digit, but it just segfaults before outputting anything. What am I doing wrong now? Here's the code: section .data

section .text
global main

printchar:
push ebp
mov ebp, esp

mov eax, 4
mov ebx, 1
mov ecx, dword [ebp + 8]
mov edx, 1
int 80H

leave
ret

putdec_unsigned:
push ebp
mov ebp, esp

mov eax, dword [ebp + 8]
mov ebx, -1
push ebx

.startwhile:
mov edx, 0
mov ebx, 10
idiv ebx
push edx
cmp eax, 0
jne .startwhile

.startloop:
pop eax
cmp eax, -1
je .endloop
push eax
call printchar
pop eax
jmp .startloop

.endloop:
mov ebx, 10
push ebx
call printchar
pop ebx

leave
ret

putdec:
push ebp
mov ebp, esp

mov eax, dword [ebp + 8]
push eax
cmp eax, 0
jnl .endif
mov ebx, 45
push ebx
call printchar
pop ebx

.endif:
pop eax
neg eax
push eax
call putdec_unsigned
pop eax

leave
ret

main:
push ebp
mov ebp, esp

mov eax, -1
push eax
call putdec
pop eax
mov eax, -32768
push eax
call putdec
pop eax
mov eax, -32767
push eax
call putdec
pop eax
mov eax, 1000
push eax
call putdec
pop eax
mov eax, -100

.startwhile:
cmp eax, 100
jg .endwhile
push eax
call putdec
pop eax
add eax, 10
jmp .startwhile

.endwhile:
mov eax, 1
push eax
call putdec
pop eax
mov eax, 32767
push eax
call putdec
pop eax
mov eax, 1000
push eax
call putdec
pop eax
mov eax, 109
push eax
call putdec
pop eax
mov eax, -2
push eax
call putdec
pop eax
mov eax, -1024
push eax
call putdec
pop eax

leave
ret

One thing I know that's wrong is that I forgot to add the ASCII '0' to each digit before trying to display it, but even after I fixed that it still blew up before outputting anything. HELP PLEASE!!!

TacKat
02-13-2002, 06:33 PM
It's not blowing up before it outputs anything, it's not outputing anything and *then* blowing up. Here's your seg fault:

call putdec
pop eax
mov eax, -1024
push eax
call putdec
pop eax

leave
ret


You don't `ret' to end execution, you have to use:


mov ebx,0 ;no error return code
mov eax,1
int 80h


Now for why you aren't getting anything displayed. When you call write (eax=4 int80h) the ecx parameter is an *address* to what you want to display. By putting ebp in brackets you are reading from wherever ebp is pointing and using that value as your address. What you're doing right now is running off to whatever happens to be at the addressed of -1, -32768, etc in binary and trying to print those values. Clearly this is not what you want; don't use brackets.

Furthermore, even without brackets it isn't going to do what you want because it will be printing the ASCII character that corresponds to -1, -32768, etc; NOT the number itself. To do what you want, you need to declare some .data or .bss. Fill that with your ASCII values for the numbers and use that memory address to print. Append a 'Ah' to the end of the string if you want a carriage return. Also, you need to be sure to set your edx to the proper value when you call write. It should be set to the number of bytes of output (the length of the string including CR).

Additionally, you are pushing and popping like a madman. Follow your program through from the beginning. You put -1 in eax and push it. You then call putdec which then reads that pushed value in and pushes it again! There is an excess of pushing going on here. If you pushed a value once, you don't really need to read it from the stack and push it again. In fact, the only thing between your two copies of -1 is the value of ebp.

Isn't assembly fun? :)

[ 13 February 2002: Message edited by: TacKat ]

Minime80
02-14-2002, 04:50 AM
Hey, thanks. I'll play with it tomorrow. BTW, that first -1 is pushed because it is going to be used as a marker for the end of the number being displayed since it's getting the value, using repeated division by 10 to get each single digit and pushing them on the stack since they are in backwards order from the repeated division, then popping each digit off the stack and displaying it... so I need a value to know when I'm done. I used -1 cause if the number is negative I just output the '-' to the screen and then negate the value so I know all those numbers will be positive. And the second -1 is pushed because it is the first value I wanted to test. And finally, the reason I'm pushing and popping so much is because I'm passing the values as parameters so the testing harness (in main) pushes a value and calls putdec, then pops it, and pushes another value, and calls putdec... etc.