Unicorn is a multi-platform multi-architecture CPU emulator based on Qemu. It is written in C and has bindings for several programming languages e. g. python, ruby, Java, go.
A mode of modern x86 CPUs is called Protected Mode. This mode offers features such as virtual memory and paging. The memory is split into segments and the segment points to them. Since the segment registers are 16bit registers they ca
nnot hold the address of a segment. Instead of the addresses to the segments the segments registers hold segment selectors which are an indices of the global or local descriptor table (GDT, LDT). You can find here and here more information about these topics.
If you use Unicorn it is not needed to create a GDT and set the GDT register (GDTR). But in some cases the segment registers have to be set to a proper value, e. g. executing Linux or Windows binaries.
To write more readable code I use some constants:
To create the GDT and the selector for the segment register I wrote some little helper functions:
In my example I create three memory regions:
Memory for GDT
Memory for the segment
Memory for the code
Now I fill the memory and the registers with the needed values. The first entry of the GDT has to be 0, therefore I start writing the entry at GDT_ADDR + GDT_ENTRY_SIZE.
The last step is to execute the code which uses the segment registers to access memory.