Was mir bei deinem Programm fehlt ist die Interrupt Vektortabelle.
Eigentlich müsste dein Programm auch ohne funktionieren, ich würd Sie aber trotzdem immer am Anfang des Programms einfügen.

Bei den zuweisungen für den SPL und SPH kenn ich das mit
ldi r16,low(ramend)
...
ldi r16,high(ramend)
...
Ob das auch mit deinen Zuweisungen geht weiß ich nicht.

Da Du aber keine Subroutinen verwendest sollte das auch kein Problem sein.
Lass doch mal das Stückchen Code im Simulator vom AVR Studio laufen und guck was das passiert.

Den WDR kannst Du Dir sparen, solange Du den Watchdog weder in der Hardware, noch in der Software aktiviert hast.

Vor das Programm hab ich auch immer Speicherdefinitionen gemacht.
.cseg
.org 0x0000
; Programm...

P.S. Prügel mich nicht, wenn die Syntax nich 100% stimmt, hab in Assembler schon länger nichts mehr gemacht.