I'd argue writing an emulator is actually quite difficult. Due to the avalanche effect, slight errors in your emulation won't cause the emulated system to be slightly off, but it makes it completely unbootable, similar to how a bug in a (cryptographic) hash function can make the output entirely different from what it's intended to be. And unless there is an existing emulator you can compare against, debugging such bugs is very difficult and they can only be identified by painstakingly cross-referencing your entire implementation with the CPU specs. Years ago I wrote an Intel 8086 emulator and even the decoding of the instructions was non-trivial: the whole deal with MOD R/M encoding and prefix bytes can take considerable time to get perfectly right. Then there's the timer interrupt system, the IO layer, rendering the visuals by polling specific regions of memory depending on the mode, 80286+ protected mode etc.