Só é possível fazer isso executando o programa e observando quais instruções reais são enviadas para a CPU. Você poderia fazer isso, por exemplo, em uma máquina virtual VMware, que permite depurar no nível de instrução da CPU do host. Existe até um plugin do Visual Studio para este fim. Um depurador antigo regular iria funcionar se você tivesse paciência para passar pelo código no nível da instrução; no entanto, um depurador não permitirá que você interrompa um intervalo específico de opcode ou opcode.
Os programas podem emitir instruções nativas para serem executadas em tempo de execução, que não estão incluídas nas seções de código do executável. Se não fosse por esse comportamento, linguagens interpretadas como Java, .NET e JavaScript seriam terrivelmente lentas. Ao permitir que o código seja gravado em tempo de execução, as linguagens de script de alto nível podem ser compiladas em código nativo e armazenadas na RAM dinamicamente enquanto o código é executado mais rápido nos casos reais de uso do aplicativo (por exemplo, se uma determinada ramificação nunca é executada , elimine esse ramo do código nativo). Isso é chamado de compilação JIT.
Mesmo alguns programas nativos fazem algo semelhante à compilação JIT, em que o código bruto no binário no disco pode ser compatível até 486, mas o programa determinará dinamicamente processador em execução e gerar código para ser executado nesse processador ou usar algum código que esteja na seção "data" do binário como código executável.
Aqui é por isso que um depurador tradicional como gdb
não permitirá que você interrompa um código de operação específico ou uma instrução de montagem . Uma solução semiperformante para esse problema provavelmente envolverá algum tipo de máquina virtual, já que o hypervisor pode ver exatamente qual código o guest com hypervisor está executando e fornecer isso como saída para um programa ou uma interface com o usuário no host.