Serial differenciation...

It all comes down to timing. When you upload a new sketch from the IDE it opens the serial port. This toggles the DTE handshaking signal of RS232. The Arduino has the DTE signal hardwired into the reset circuit. (This is why your Arduino resets when you open the Serial Monitor. You may not have noticed it before, but it does.) Then a "helper" utility that is distributed as part of the IDE called "avrdude" kicks in and communicates with the Arduino (hopefully the bootloader on the Arduino).

When the Arduino is reset it starts executing the first bit of code in it's memory, the bootloader. If the bootloader then sees the right message come in over the RX line (I actually don't know this message, but I don't need to because I'm not into modifying bootloaders or avrdude) it will respond and (I would imagine) perform a quick handshake with avrdude to load a new sketch. If it doesn't see that message after a set period of time (I'm not quite sure what it is, but I'm sure applying google-fu could answer it) the bootloader times out and then hands execution to the previously loaded sketch which never releases execution control (barring a reset command or intentionally mucking with the execution pointer with assembler code). Because the bootloader doesn't (normally) execute again you can't accidentally force it to load data into sketch space. I suppose one could be extremely unlucky and have an incoming serial stream on digital pin 0 when during a manual reset with the reset button (or after a power glitch) that the bootloader would mistake as a command and normal handshaking between the bootloader and avrdude to overwrite the sketch space, but IMHO that would be extremely rare, bordering on nearly impossible. (But I could be wrong...)

Edit: Or what vaj4088 said... :wink: