At the end of an interrupt routine or sub routine you need to tell the assembler that you need to go back to the point where it was called. For interrupt you use RTI (return from interrupt) and from sub routine you use RTS (return from sub routine). What it basically does is that it "return" to the address before the NMI or sub routine was called.
As for the reason that it goes haywire, all your logic is called from the NMI. This is a big no-no on the nes. NMI should be only used to do critical things like updating the screen. This logic should be done outside the nmi, in your game loop. For now, your code doesn't have any: there is only a forever loop. If you want your code to work properly, you will need to put the logic at the right place. Of course this is something you cannot guess from the first time you write code on the nes.
One approach is to put a flag that is updated in NMI (a counter for example), once NMI is over, the counter will be updated. In the "forever" loop, you wait that the coutner change. Once this is done, this is when you can do your collision detection logic.
I'm concerned about this comment thought:
Do you know about the basics of programming at the least? If not, this will make you life quite a living hell by starting to program on the nes. The nes is not very forgiving if you make any mistakes. I don't say that it's not possible, some people here did and succeeded but if you really don't have any background in programming, I would suggest that you read a little bit about the fundamentals like what are variables, loops etc. That will help you in the end.Please keep in mind as you read this (and especially if you look at my amatuerish code in the .asm files) that I am a VERY green noob and not a programmer.