That situation is covered in this section:
http://andrewkelley.me/post/jamulator.html#dirty-assembly-tr...Basically I embed an interpreter runtime and use it only when necessary, such as in the case when the program jumps to RAM.
Good point though. I should specifically mention self-modifying code.
Note that with NES games, self modifying code is uncommon, because programs are 32 KB ROM, and you only have 2KB RAM. So you'd have to first copy your subroutine from ROM to RAM, and then jump to it. And then you have that much less RAM to work with.
However, some of the emulator test ROMs[1] people have made use this technique to test every instruction.
[1]: http://wiki.nesdev.com/w/index.php/Emulator_tests