is there such a thing as "compiler, but for OSes"?
If all you have is the "the machine code of the operating system", then I assume you are referring to the executable binary image of the kernel.
In theory the machine code of one CPU can be translated to the machine code of a CPU of a different architecture. But that typically requires the disassembly (that is, the reverse translation from machine code) of the executable to assembly language. Disassembly facilitates the handling of (memory) addresses for branches, calls, and variables by using symbolic labels (instead of the numeric memory addresses as used in machine code).
Disassembly of an executable binary image is complicated because of the necessity to distinguish data from code. The organization or layout of such binaries is machine and compiler dependent.
Even if you manage to translate the machine code to another machine, you would still be stuck with the code implementing procedures for the original system. The executable binary image of the kernel contains control sequences written specifically for a certain type of hardware. The steps to control and access that hardware, such as a specific peripheral device, are in that code. There is no automated translation or conversion of such procedures for some other hardware system. There are too many nuances to adapt kernel code to a different machine/architecture, so it must be done by hand.
There is no mechanism currently in existence that will "intelligently create a new machine code" for you.
Addendum
And that the place in which they get these instruction is from the drive.
The CPU (of a conventional digital computer) fetches the (next) instruction from the location specified by the Program Counter register (aka Instruction Pointer). That location would be a memory address.
Instructions are fetched from (main) memory, and not "from the drive".
See Run a computer without RAM?
And my idea is to translate all the code beforehand rather than in real time as I perceive virtualization softwares do.
[You seem to be conflating virtualization and emulation. Learn the differences. See https://stackoverflow.com/questions/6044978/full-emulation-vs-full-virtualization .]
Emulation performs an actual execution path through the executable. The executable image will always have a starting address, i.e. the location of the first instruction (in machine code) to execute. Sequential locations are accessed for subsequent instructions, unless a branch or call or return instruction is "executed", or an interrupt is handled.
Executing (natively or emulating a CPU) an image conveniently identifies the locations that are instructions and data. Locations would be accessed as instructions as those location are executed.
Locations would be accessed for data when referenced by an instruction operand or indirectly through a register.
But emulation will likely only "execute" a portion of the locations in the entire executable image. There will be many locations never referenced or accessed, and hence would not be known to be definitively a location containing an instruction or a datum.
The task of identifying the usage of each and every location can be tedious and complicated.
Are there any assurances that there is no self-modifying code?
Are there any assurances that there is no hidden data mixed in the code, or vice-versa?
Translating an opcode to another instruction set is typically straight-forward. But identifying each instruction versus the data in an executable image cannot always be performed reliably, especially if the instructions have variable length (e.g. Intel x86 instructions).
Translating the instruction set is just the first problem of translating the executable image. Translating the instruction set only represents the change of CPU. Beyond the CPU are the system bus(es) and peripherals. How is the code going to be "translated" to perform different procedures for this different system?
If the executable was a userspace program for a given OS, then hardware details are abstracted by the OS. Such an executable would have minimal hardware dependencies other than the CPU, and the conversion process is greatly simplified.
But since you specified that the executable was the OS (which I interpret to be a kernel), then that is the code that is supposed to implement that hardware abstraction. Such an executable would have many hardware dependencies besides the CPU, and the conversion process is greatly complicated.