Quando você compila um programa .NET, o MSIL (pode ser chamado de CIL agora) é gerado. MSIL é um "byte-code" - algo como uma linguagem assembly de nível ligeiramente superior que não foi projetada para rodar em qualquer CPU real.
Isso deve ser "just-in-time" compilado (JITted) para o código nativo. Sua CPU só entende o código nativo. O código nativo é específico da arquitetura, ou seja, o código nativo do ARM não funciona no x86 e vice-versa.
O código do objeto é o que um montador ou compilador gera antes de ser colocado em um processo chamado de vinculação. Simplificando, a vinculação permite que o código use sub-rotinas, funções e APIs em outras bibliotecas (como .dlls), frameworks (como COM, etc.) e o próprio sistema operacional - após vincular, você tem um executável que pode usar. O código do objeto também é específico da arquitetura.
O compilador JIT não invoca um programa separado para criar assembly (não no Windows, de qualquer maneira) - não há um arquivo intermediário de texto assembly "linguagem assembly" criado. Tenho certeza que apenas emite diretamente as instruções binárias em si. Você pode fazer engenharia reversa e desmontá-la como faria com qualquer outro .exe. Isso é muito complicado e geralmente dá muito trabalho.
Todo o código, seja texto, fonte, nativo, máquina, assembly, objeto, etc., é um fluxo de dados binários. Ele acaba assim na memória da CPU quando é carregado. Quando armazenado em um arquivo, ele geralmente é empacotado em um formato executável (Portable Executable ou PE no Windows) que também contém dados adicionais, colocados em outro lugar na RAM quando carregados em uma solicitação de execução do SO, como dados estáticos referenciados pelo programa (inteiros e seqüências de caracteres constantes, recursos como ícones, etc.), as DLLs que ele usa e outras coisas. Referências para o formato PE estão prontamente disponíveis.