This puzzled me for a while. I know that sys_write will print 500 bytes, if we ask it to, regardless of whether there's anything "interesting" there. But where do all the copies of the string come from? Well, I think they come from right here:
nloop: ;exit the loops if we have reached our maximum size
cmp ecx, 500
je endloopS
mov eax, [msg+edx]
mov [input+ecx], eax ;append the two strings together
inc edx
inc ecx
jmp nloop
You don't look for the linefeed that ends "msg", so after concatenating "msg" to the user input you proceed into the input buffer and keep concatenating itself to itself until you've moved a full 500 characters. I think that's why your program repeats itself.
cmp al, 10 ; linefeed? end of "msg"? Note: al, not eax!
je endloopS
Something like that should fix it. You'll still be printing 500 mostly useless bytes, but at least they'll be zeros!
You could take a slightly different approach to this. When sys_read returns, the number of bytes actually read is in eax. This includes the linefeed caused by hitting "enter" to end input. So we know where the linefeed is, without having to walk down the string looking for it. We want to back up one, and overwrite the linefeed with the '@' from "msg". The length of "msg" is known, so we know how many bytes to move without looking for the end of that, either. When it comes to printing out the results, the length of user input (not counting the linefeed) plus the length of "msg" ought to be the number we want in edx for the sys_write to print just the number of characters we need. I think you might get a "better" program out of it, but the way you're doing it is okay too.
Don't apologize for posting a lot! I hope we hear more from you. Compared to the guys who want to know "do u haz the kode?", you're a pleasure to try to help!
Best,
Frank