Kompilatory zazwyczaj najpierw tłumaczą kod źródłowy danego języka, na kod języka asemblera, a następnie kod języka asemblera jest asemblowany do kodu maszynowego. Po prostu poszczególnym rozkazom odpowiadają odpowiednie wartości liczbowe (patrz: opcode). Przykładowo, u mnie rozkaz:
mov eax, 3
Został "zamieniony" na kod maszynowy:
66 B8 03 00 00 00
Tutaj masz jakieś materiały na temat pisania kompilatora: https://compilers.iecc.com/crenshaw/ "Odrobinę" stare (bardzo stare), ale może wyciągniesz z nich coś ciekawego.