This processor does have a jump instruction, but putting everything in copy_flash would be better. And the assumption the the return address is at the top of the stack breaks when optimisation is not enabled. What registers can be changed by a function is irrelevant here. The question is what inline assembler is allowed to do, whilst Visual C++ will parse inline assembler to determine register usage, GCC will not. If one of the registers has been allocated for another purpose by the compiler, it will break. Neither Visual C++ or GCC guarantees that registers will remain unchanged between consecutive asm statements. If profiling is enabled this code will break.