Muitos anos atrás, passei uma manhã tentando depurar algum código auto-modificável; uma instrução alterou o endereço de destino da instrução a seguir, ou seja, eu estava computando um endereço de filial. Foi escrito em linguagem assembly e funcionou perfeitamente quando eu percorri o programa, uma instrução de cada vez. Mas quando eu executei o programa falhou. Eventualmente, eu percebi que a máquina estava buscando 2 instruções da memória e (como as instruções foram dispostas na memória) a instrução que eu estava modificando já havia sido buscada e, portanto, a máquina estava executando a versão não modificada (incorreta) da instrução. Obviamente, quando eu estava depurando, ele fazia apenas uma instrução por vez.
Meu ponto de vista, o código auto-modificável pode ser extremamente desagradável para testar / depurar e muitas vezes tem suposições ocultas quanto ao comportamento da máquina (seja hardware ou virtual). Além disso, o sistema nunca pôde compartilhar páginas de código entre os vários threads / processos em execução nas (agora) máquinas com vários núcleos. Isso anula muitos dos benefícios da memória virtual, etc. Também invalidaria as otimizações de ramificações feitas no nível do hardware.
(Nota - eu não incluí o JIT na categoria de código auto-modificável. O JIT está traduzindo de uma representação do código para uma representação alternativa, não está modificando o código)
No geral, é apenas uma péssima idéia - muito legal, muito obscura, mas muito ruim.
é claro - se tudo o que você tem são 8080 e ~ 512 bytes de memória, talvez seja necessário recorrer a essas práticas.