No, your code isn't COMPLETELY screwed up. The "exit" is right.
It does have some problems!
SECTION .bss ; mutable/modifiable variables
msg: resb 1
SECTION .text
global _start
_start:
call read
call write
mov eax, msg
This puts the address of msg into eax. It's 0x8049000-and-some - never 10. You want "[msg]", ("[contents]" of memory) but I'm not sure that'll do what you want, either...
cmp eax, 10
jne _start
mov eax, 1
int 80h
Okay, but now you go into a weird mix of C and sys_call calling conventions...
read:
mov eax, 3
push 1
mov ebx, [msg]
push ebx
push 0
int 80h
ret
Here's where your segfault comes from. It is not obvious to beginners, but "call" and "ret" use the stack. "call read" put the return address (the address right after this instruction) on the stack. When you get to "ret", you return to the address on the stack. Since you pushed 0... program go "boom".
The way a "read" should go is more like...
read:
mov eax, 3 ; system call number for "read"
mov ebx, 0 ; file descriptor to read from 0=stdin
mov ecx, msg ; address of our buffer
mov edx, 1 ; how many (max) bytes to read
int 80h ; call kernel
ret ; since we didn't push anything, this is okay
What really happens here is that sys_read on stdin doesn't return until you hit a linefeed (the 10 you're looking for). If the user types "abc(enter)", the system call doesn't return until we hit "enter", but since we only asked for one character, the "a" goes into the buffer (msg), the "bc(enter)" stays in the OS's input buffer. If you exited right now, you'd execute the program "bc" (some sort of calculator, apparently). Since you go back and "call read" again, it'll get "b" the next time, then "c", then the 10 you're looking for. So it'll work, but doesn't really do what it appears to.
There's a way to make sys_read return without waiting for the "enter", but it's complicated, and I'm not satisfied with the way I do it.
When you look for the 10, you do:
mov eax, [msg]
well... you put the address, not the contents, but... using eax gets the contents of msg - and the next three bytes! Chances are, the next three bytes are 0s in this case, so it'll probably work, but you probably want to use al to get just the one byte you've got in the buffer:
mov al, [msg]
cmp al, 10
...
You've got a similar problem in "write"...
write:
mov eax, 4
push 1
mov ebx, [msg]
push ebx
push 1
int 80h
ret
This, too, would segfault if you got to it. More like...
write:
mov eax, 4 ; sys_call number for "sys_write"
mov ebx, 1 ; file descriptor 1=stdout
mov ecx, msg ; address of buffer
mov edx, 1 ; how many?
int 80h
ret
See if that helps. There are some tutorials on the subject here:
http://asm.sourceforge.net/resources.html#tutorialsBest,
Frank