The virtual machine doesn't have a name yet, but to keep it short, we refer to it as
the machine.
This document contains the specification of the binary encoding of instructions, immediate values, constants, registers, jump addresses, block ordering and global constants.
+----------+
| Header |
+----------+
| Segments |
+----------+
| Name | Offset | Size | Description |
|---|---|---|---|
| magic | 0x00 |
4 |
ascii encoded string NICE |
| entry_addr | 0x04 |
4 |
Initial value of the ip register |
| load_table_size | 0x08 |
4 |
Number of entries in the load table |
| load_table | 0x0c |
load_table_size * 12 |
Load table |
The load table in the programs header section includes 1 or more entries.
Each entry is structured as follows:
| Name | Offset | Size | Description |
|---|---|---|---|
| Offset | 0x0 |
4 |
Start offset of section |
| Size | 0x4 |
4 |
Size of section |
| Load | 0x8 |
4 |
Target offset in machine's memory |
Given the following load table:
| ID | Offset | Size | Load |
|---|---|---|---|
0 |
0x00000000 |
0x000002aa |
0x00337a00 |
1 |
0x000002aa |
0x00337a00 |
0x00000000 |
2 |
0x00337caa |
0x00000050 |
0x00000050 |
3 |
0x00337cfa |
0x00000100 |
0x00700000 |
The executable would consist of four segments.
+-----------+ <- 0x00000000
| Segment 0 |
+-----------+ <- 0x000002aa
| Segment 1 |
+-----------+ <- 0x00337caa
| Segment 2 |
+-----------+ <- 0x00337cfa
| Segment 3 |
+-----------+ <- 0x00337dfa
This is how they would ultimately be laid out in memory:
+-------------+ <- 0x00000000
| Segment 1 |
| |
+-------------+ <- 0x00000050
| Segment 2 | <----------------- Because the load address of Segment 2 is set to 0x00000050,
+-------------+ <- 0x000000a0 it overlaps Segment 1 which was loaded here before.
| Segment 1 |
| |
| |
| |
| |
| |
| |
+-------------+ <- 0x00337a00
| Segment 0 |
| |
| |
+-------------+ <- 0x00337caa
| |
| |
| |
| |
| |
| |
| ... |
| Empty space |
| ... |
| |
| |
| |
| |
| |
| |
+-------------+ <- 0x00700000
| Segment 3 |
+-------------+ <- 0x00700100
Registers are represented as 8 bit values. The first two bits make up the mode, the rest is the register code.
+- Register code
|
v
00 000000
^
|
+- Mode
Register modes define which part of the register is being accessed.
00: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
01: 00000000 00000000 00000000 00000000
10: 00000000 00000000
11: 00000000
Instructions are represented as 8 bit values.
+- Opcode
|
v
00000000
Size specifiers are encoded as unsigned dword values and are used to denote
a given amount of bytes in an instruction argument.
Addresses are encoded as unsigned dword values.
Relative offsets are encoded as signed dword values.