Can someone explain the principles of writing an emulator?
Usually, start with the CPU. For that, at the simplest level you create a data structure that represents your emulated CPU (all the registers etc).
You then write code to fetch instructions from wherever the emulated PC (program counter) is pointing, decode their operands (if any), do whatever the emulated instruction does and update the data in your structure and any "emulated" memory region that would be altered accordingly. You do this in a loop until a certain number of instructions have been executed or some special condition (an interrupt or whatever) is set.
There are 2 basic ways to write that type interpreter. One uses a big switch/case construct for every possible instruction opcode. The other uses a table of function pointers which are indexed by opcode value. Each has advantages and disadvantages.
If you know your emulated CPU and target CPU very well, you may be able to write a JIT. It's rather more complicated, however.