diff --git a/source/assembler.c b/source/assembler.c index f92530b..0319788 100644 --- a/source/assembler.c +++ b/source/assembler.c @@ -2,7 +2,6 @@ #include #include -#include "debug.h" #define REGULAR_BEGIN (ADD) #define REGULAR_END (CMP) @@ -17,46 +16,43 @@ #define MOVE_IF_BEGIN (CMOVO) #define MOVE_IF_END (CMOVG) -#define REGULAR_COUNT (REGULAR_END - REGULAR_BEGIN + 1) -#define IRREGULAR_COUNT (IRREGULAR_END - IRREGULAR_BEGIN + 1) -#define SPECIAL_1_COUNT (SPECIAL_1_END - SPECIAL_1_BEGIN + 1) -#define SPECIAL_2_COUNT (SPECIAL_2_END - SPECIAL_2_BEGIN + 1) -#define JUMP_IF_COUNT (JUMP_IF_END - JUMP_IF_BEGIN + 1) -#define MOVE_IF_COUNT (MOVE_IF_END - MOVE_IF_BEGIN + 1) +#define REGULAR_COUNT (REGULAR_END - REGULAR_BEGIN + 1) // 16 +#define IRREGULAR_COUNT (IRREGULAR_END - IRREGULAR_BEGIN + 1) // 16 +#define SPECIAL_1_COUNT (SPECIAL_1_END - SPECIAL_1_BEGIN + 1) // 6 +#define SPECIAL_2_COUNT (SPECIAL_2_END - SPECIAL_2_BEGIN + 1) // 6 +#define JUMP_IF_COUNT (JUMP_IF_END - JUMP_IF_BEGIN + 1) // 16 +#define MOVE_IF_COUNT (MOVE_IF_END - MOVE_IF_BEGIN + 1) // 16 -// Regulates displacement, immediate, label, variable, constant, string data. -#define TESTING_FOR_NOW (4) -static next empty_count = 0; -static next empty_holes = 0; -static next empty_array [TESTING_FOR_NOW] = { 0 }; -static next empty_imbue [TESTING_FOR_NOW] = { 0 }; -static next empty_store [TESTING_FOR_NOW] = { 0 }; +static int assemble_clean_up_queued = 0; -// Main function. -static void place (form when, +static next empty_count = 0; +static next empty_holes = 0; +static next * empty_array = NULL; +static next * empty_imbue = NULL; +static next * empty_store = NULL; + +static void input (form when, byte data) { - /* */ + // Input one byte to text sector. text_sector_byte [text_sector_size] = data; text_sector_size += (next) when; } -static void print (form when, - size_index size, - next data) { - /* */ - place ((when != 0) && (size >= D8), (byte) ((data >> 0) & 0xff)); - place ((when != 0) && (size >= D16), (byte) ((data >> 8) & 0xff)); - place ((when != 0) && (size >= D32), (byte) ((data >> 16) & 0xff)); - place ((when != 0) && (size >= D32), (byte) ((data >> 24) & 0xff)); - /* 64-BIT SUPPORT */ +static void input_by (form when, + size_index size, + next data) { + // Input size-dependent bytes to text sector. + input ((when != 0) && (size >= D8), (byte) ((data >> 0) & 0xff)); + input ((when != 0) && (size >= D16), (byte) ((data >> 8) & 0xff)); + input ((when != 0) && (size >= D32), (byte) ((data >> 16) & 0xff)); + input ((when != 0) && (size >= D32), (byte) ((data >> 24) & 0xff)); + // 64-BIT SUPPORT } static void asmdirrel (form when, next data) { - /* */ - if (empty_holes >= TESTING_FOR_NOW) exit (69); - + // Assembler directive, queue relative memory address. empty_array [empty_holes] = text_sector_size; empty_imbue [empty_holes] = data; @@ -65,121 +61,120 @@ static void asmdirrel (form when, static void asmdirmem (form when, next code) { - /* */ - if (code >= TESTING_FOR_NOW) exit (69); - + // Assembler directive, queue memory address. empty_store [code] = text_sector_size; empty_count += (next) when; } -static void delay (form when, - size_index size, - next data) { - /* */ - asmdirrel (when, data); - - place ((when != 0) && (size >= D8), (byte) 0xb0); - place ((when != 0) && (size >= D16), (byte) 0x10); - place ((when != 0) && (size >= D32), (byte) 0x40); - place ((when != 0) && (size >= D32), (byte) 0x00); - /* NO DEREFERENCING */ - /* 64-BIT SUPPORT */ -} - static void asmdirimm (form when, size_index size, next data) { - print (when, size, data); + // Assembler directive, queue immediate value at current size. + input_by (when, size, data); +} + +static void input_at (form when, + size_index size, + next data) { + // Input relative memory address to text sector. + asmdirrel (when, data); + + input ((when != 0) && (size >= D8), (byte) 0xb0); + input ((when != 0) && (size >= D16), (byte) 0x10); + input ((when != 0) && (size >= D32), (byte) 0x40); + input ((when != 0) && (size >= D32), (byte) 0x00); + // NO DEREFERENCING + // 64-BIT SUPPORT } static form front (form data) { return ((data >= 4) && (data <= 7)); } static form lower (form data) { return ((data >= 0) && (data <= 7)); } static form upper (form data) { return ((data >= 8) && (data <= 15)); } -// Important stuff that I need to handle later, it saves bytes! -static form far (next label) { return (label && 1); } -static form near (next label) { return (label && 0); } +static form far (next label) { return (label && 1); } // Unused for now. +static form near (next label) { return (label && 0); } // Unused for now. static void build_short_prefix (form when) { - place (when, 0x66); + // 66 + input (when, 0x66); } -// 40-4D!0X02 -static void build_long_prefix (form use_big_registers, - form use_new_destination, - form use_new_source) { - /* */ - place (use_big_registers || use_new_destination || use_new_source, +static void build_long_prefix (form big_registers, + form new_destination, + form new_source) { + // 40-4D!0X02 + input (big_registers || new_destination || new_source, (byte) (0x40 - + 0x01 * use_new_destination - + 0x04 * use_new_source - + 0x08 * use_big_registers)); + + 0x01 * new_destination + + 0x04 * new_source + + 0x08 * big_registers)); } -// C0-FF static void build_register_direction (form when, next destination, next source) { - /* */ - place (when, (byte) (0xc0 - + 0x01 * (destination & 0x07) - + 0x08 * (source & 0x07))); + // C0-FF + input (when, + (byte) (0xc0 + + 0x01 * (destination & 0x07) + + 0x08 * (source & 0x07))); } -// 05-3D static void build_register_redirection (form when, next direction) { - /* */ - place (when, (byte) (0x05 - + 0x08 * (direction & 0x07))); + // 05-3D + input (when, + (byte) (0x05 + + 0x08 * (direction & 0x07))); } -// 80/81 static void build_constant (form when, size_index size) { - /* */ - place (when, (byte) (0x80 - + 0x01 * (size != D8))); + // 80/81 + input (when, + (byte) (0x80 + + 0x01 * (size != D8))); } -// REGULAR_BEGIN-REGULAR_END D8-D64 REG/MEM R0-R15/MEM -||-/IMM -||-/IMM static void build_regular (operation_index operation, size_index size, type_index to, next destination, type_index from, next source) { - /* */ + // 00-3F : add, or, adc, sbb, and, sub, xor, cmp build_short_prefix (size == D16); build_long_prefix (size == D64, - (to == REG) && (upper ((form) destination)), - (from == REG) && (upper ((form) source))); + (to == REG) && (upper ((form) destination)), + (from == REG) && (upper ((form) source))); - // 40>front - place ((size == D8) && (to == REG) && ((from == REG) || (from == IMM)) - && (((front ((form) destination) && lower ((form) source)) - || (lower ((form) destination) && front ((form) source))) || - ((to == REG) && (from == IMM) && front ((form) destination))), - (byte) 0x40); + input ((size == D8) + && (to == REG) + && ((from == REG) || (from == IMM)) + && (((front ((form) destination) && lower ((form) source)) // + || (lower ((form) destination) && front ((form) source))) // + || ((to == REG) && (from == IMM) && front ((form) destination))), + (byte) 0x40); - place ((from == IMM) && (to == REG) && (destination == 0), - (byte) (0x05 - + 0x08 * (operation & 0x07)) - - 0x01 * (size == D8)); + input ((from == IMM) && (to == REG) && (destination == 0), + (byte) (0x05 + + 0x08 * (operation & 0x07)) + - 0x01 * (size == D8)); - build_constant ((from == IMM) && ! ((to == REG) && (destination == 0)), size); + build_constant ((from == IMM) && ! ((to == REG) && (destination == 0)), + size); - place (! ((from == IMM) && (to == REG) && (destination == 0)), - (byte) (0x08 * (operation - REGULAR_BEGIN) - + (destination & 0x07) * ((to == REG) && (from == IMM)) - + 0x01 * ((to == MEM) && (from == IMM) && (size == D8)) // - - 0x01 * ((to == REG) && (from == IMM) && (size != D8)) // - + 0x01 * (size != D8) - + 0x02 * ((to == REG) && (from == MEM)) - + 0x04 * ((to == MEM) && (from == IMM)) - + 0xc0 * ((to == REG) && (from == IMM)))); + input (! ((from == IMM) && (to == REG) && (destination == 0)), + (byte) (0x08 * (operation - REGULAR_BEGIN) + + 0x01 * ((to == MEM) && (from == IMM) && (size == D8)) + - 0x01 * ((to == REG) && (from == IMM) && (size != D8)) + + 0x01 * (size != D8) + + 0x02 * ((to == REG) && (from == MEM)) + + 0x04 * ((to == MEM) && (from == IMM)) + + 0xc0 * ((to == REG) && (from == IMM))) + + (destination & 0x07) * ((to == REG) && (from == IMM))); build_register_direction ((to == REG) && (from == REG), destination, source); @@ -187,147 +182,157 @@ static void build_regular (operation_index operation, build_register_redirection ((to == REG) && (from == MEM), destination); build_register_redirection ((to == MEM) && (from == REG), source); - print ((to == REG) && (from == MEM), D32, (next) ~0); - print ((to == REG) && (from == IMM), size, source); - print ((to == MEM) && (from == REG), D32, (next) ~0); - print ((to == MEM) && (from == IMM), D32, (next) ~0); - print ((to == MEM) && (from == IMM), size, source); + input_by ((to == REG) && (from == MEM), D32, (next) ~0); + input_by ((to == REG) && (from == IMM), size, source); + input_by ((to == MEM) && (from == REG), D32, (next) ~0); + input_by ((to == MEM) && (from == IMM), D32, (next) ~0); + input_by ((to == MEM) && (from == IMM), size, source); } -// IRREGULAR_BEGIN-IRREGULAR_END D8-D64 REG/MEM R0-R15/MEM static void build_irregular (operation_index operation, size_index size, type_index to, next destination) { - /* */ + // F0-FF : inc, dec, not, neg, mul, imul, div, idiv build_short_prefix (size == D16); build_long_prefix (size == D64, - (to == REG) && (upper ((form) destination)), 0); + (to == REG) && (upper ((form) destination)), 0); - // 40>front - place ((size == D8) && (to == REG) && front ((form) destination), (byte) 0x40); + input ((size == D8) && (to == REG) && front ((form) destination), + (byte) 0x40); - place (1, (byte) (0xf7 - + 0x08 * ((operation == INC) || (operation == DEC)) - - 0x01 * (size == D8))); + input (1, + (byte) (0xf7 + + 0x08 * ((operation == INC) || (operation == DEC)) + - 0x01 * (size == D8))); - place (to == REG, (byte) (0xc0 - + 0x08 * (operation - IRREGULAR_BEGIN)) - + 0x01 * (destination & 0x07)); + input (to == REG, + (byte) (0xc0 + + 0x08 * (operation - IRREGULAR_BEGIN)) + + 0x01 * (destination & 0x07)); - place (to == MEM, (byte) (0x05 - + 0x08 * (operation - IRREGULAR_BEGIN))); + input (to == MEM, + (byte) (0x05 + + 0x08 * (operation - IRREGULAR_BEGIN))); } -// SPECIAL_1_BEGIN-SPECIAL_1_END static void build_special_1 (operation_index operation) { + // nop, retn, retf, leave, lock, hlt const byte data [1 * SPECIAL_1_COUNT] = { 0x90, 0xc3, 0xcb, 0xc9, 0xf0, 0xf4 }; - place (1, data [operation - SPECIAL_1_BEGIN]); + input (1, data [operation - SPECIAL_1_BEGIN]); } -// SPECIAL_2_BEGIN-SPECIAL_2_END static void build_special_2 (operation_index operation) { + // sysenter, sysleave, syscall, sysret, pause, cpuid const byte data [2 * SPECIAL_2_COUNT] = { 0x0f, 0x0f, 0x0f, 0x0f, 0xf3, 0x0f, 0x34, 0x35, 0x05, 0x07, 0x90, 0xa2 }; - place (1, data [operation - SPECIAL_2_BEGIN]); - place (1, data [operation - SPECIAL_2_BEGIN + SPECIAL_2_COUNT]); + input (1, data [operation - SPECIAL_2_BEGIN]); + input (1, data [operation - SPECIAL_2_BEGIN + SPECIAL_2_COUNT]); } -// JUMP_IF_BEGIN-JUMP_IF_END D8/32 IMM8/32 static void build_jump_if (operation_index operation, size_index size, next location) { - /* */ - (void) size; /* HIGHLY DEPENDS FOR FAR AND NEAR JUMPS! */ + // j** + (void) size; // For now, everything is a far jump. - place (far (location), 0x0f); /* EVERYTHING IS FAR JUMP! */ - place (far (location), (byte) (0x80 + operation - JUMP_IF_BEGIN)); - place (near (location), (byte) (0x70 + operation - JUMP_IF_BEGIN)); + input (far (location), 0x0f); + input (far (location), (byte) (0x80 + operation - JUMP_IF_BEGIN)); + input (near (location), (byte) (0x70 + operation - JUMP_IF_BEGIN)); - //~displacement (4, 0X12345678); + // displacement (4, 0X12345678); } -// MOVE_IF_BEGIN-MOVE_IF_END D16-D64 REG R0-R15 -||-/MEM -||-/MEM static void build_move_if (operation_index operation, size_index size, type_index to, next destination, type_index from, next source) { - /* */ + // cmov** build_short_prefix (size == D16); build_long_prefix (size == D64, (to == REG) && (upper ((form) destination)), (from == REG) && (upper ((form) source))); - place (1, 0x0f); - place (1, (byte) (0x40 + operation - MOVE_IF_BEGIN)); + input (1, 0x0f); + input (1, (byte) (0x40 + operation - MOVE_IF_BEGIN)); build_register_direction ((to == REG) && (from == REG), destination, source); build_register_redirection ((to == REG) && (from == MEM), destination); - //~displacement (4, 0X12345678); // Not implemented at this point! + // displacement (4, 0X12345678); // Not implemented at this point! } -// SPECIAL! static void build_jump (size_index size, type_index to, next destination) { - /* */ - place ((to == REG) && upper ((form) destination), (byte) 0X41); + // jmp + input ((to == REG) && upper ((form) destination), (byte) 0X41); - place (to == REL, (byte) (0xe9 + 0x02 * (size == D8))); - place (to == REG, (byte) 0xff); - place (to == REG, (byte) (0xe0 + 0x01 * (destination & 0x07))); - place (to == MEM, (byte) 0xff); - place (to == MEM, (byte) 0x25); + input (to == REL, (byte) (0xe9 + 0x02 * (size == D8))); + input (to == REG, (byte) 0xff); + input (to == REG, (byte) (0xe0 + 0x01 * (destination & 0x07))); + input (to == MEM, (byte) 0xff); + input (to == MEM, (byte) 0x25); - //~displacement (to == MEM, 4, 0x12345678); // Keep when in mind! + // displacement (to == MEM, 4, 0x12345678); // Keep when in mind! } -// VERY FUCKING SPECIAL! static void build_move (size_index size, type_index to, next destination, type_index from, next source) { - /* */ + // mov build_short_prefix (size == D16); build_long_prefix (size == D64, (to == REG) && (upper ((form) destination)), (from == REG) && (upper ((form) source))); - place ((to == REG) && (from == REG), (byte) (0x88 + (size != D8))); - place ((to == REG) && (from == MEM), (byte) (0x8a + (size != D8))); - place ((to == MEM) && (from == REG), (byte) (0x88 + (size != D8))); + input ((to == REG) && (from == REG), (byte) (0x88 + (size != D8))); + input ((to == REG) && (from == MEM), (byte) (0x8a + (size != D8))); + input ((to == MEM) && (from == REG), (byte) (0x88 + (size != D8))); build_register_redirection ((to == REG) && (from == MEM), destination); build_register_redirection ((to == MEM) && (from == REG), source); - place ((to == REG) && ((from == IMM) || (from == REL)), (byte) (0xb8 - //~+ 0x08 * (size != D8) - + 0x01 * (destination & 0x07))); + input ((to == REG) && ((from == IMM) || (from == REL)), + (byte) (0xb8 + // + 0x08 * (size != D8) + + 0x01 * (destination & 0x07))); - place ((to == MEM) && (from == IMM), (byte) (0xc6 + (size != D8))); - place ((to == MEM) && (from == IMM), (byte) (0x05)); + input ((to == MEM) && (from == IMM), (byte) (0xc6 + (size != D8))); + input ((to == MEM) && (from == IMM), (byte) (0x05)); - delay ((to == REG) && (from == MEM), D32, source); - print ((to == REG) && (from == IMM), size, source); - delay ((to == MEM) && (from == REG), D32, (next) ~0); - delay ((to == MEM) && (from == IMM), D32, (next) ~0); - print ((to == MEM) && (from == IMM), size, source); - delay ((to == REG) && (from == REL), D32, source); + input_at ((to == REG) && (from == MEM), D32, source); + input_by ((to == REG) && (from == IMM), size, source); + input_at ((to == MEM) && (from == REG), D32, (next) ~0); + input_at ((to == MEM) && (from == IMM), D32, (next) ~0); + input_by ((to == MEM) && (from == IMM), size, source); + input_at ((to == REG) && (from == REL), D32, source); +} + +static void assemble_clean_up (void) { + if (assemble_clean_up_queued == 0) { + return; + } + + free (text_sector_byte); + free (empty_array); + free (empty_imbue); + free (empty_store); } next text_sector_size = 0; @@ -337,8 +342,7 @@ int was_instruction_array_empty = 0; void assemble (next count, next * array) { - debug_token_dump(); - /* */ + // Main batched assembling procedure. next index; if ((count == 0) || (array == NULL)) { @@ -346,24 +350,33 @@ void assemble (next count, return; } + // Right now, batching is not supported, it will be soon. + // In that case, realloc function will be used with memset. + text_sector_byte = calloc (1440UL, sizeof (* text_sector_byte)); + empty_array = calloc (144UL, sizeof (* empty_array)); + empty_imbue = calloc (144UL, sizeof (* empty_imbue)); + empty_store = calloc (144UL, sizeof (* empty_store)); + + if (assemble_clean_up_queued == 0) { + atexit (assemble_clean_up); + assemble_clean_up_queued = ! assemble_clean_up_queued; + } + for (index = 0; index < count; ++index) { if (array [index] == ASMDIRREL) { asmdirrel (1, array [index + 1]); - debug_printf ("ASMDIRREL %u\n", array [index + 1]); index += 1; } else if (array [index] == ASMDIRMEM) { asmdirmem (1, array [index + 1]); - debug_printf ("ASMDIRMEM %u\n", array [index + 1]); index += 1; } else if (array [index] == ASMDIRIMM) { - debug_printf ("ASMDIRIMM\n"); next repeat; for (repeat = 0; repeat < array [index + 2]; ++repeat) { asmdirimm (1, array [index + 1], array [index + 3 + repeat]); } index += 2 + array [index + 2]; - //~} else if (array [index] == ASMDIRREP) { + // } else if (array [index] == ASMDIRREP) { } else if ((array [index] >= REGULAR_BEGIN) && (array [index] <= REGULAR_END)) { build_regular (array [index + 0], array [index + 1], @@ -402,13 +415,9 @@ void assemble (next count, build_move (array [index + 1], array [index + 2], array [index + 3], array [index + 4], array [index + 5]); - debug_printf ("MOV %i %i %i %i %i\n", - array [index + 1], array [index + 2], - array [index + 3], array [index + 4], - array [index + 5]); index += 5; } else { - //~exit (array [index]); // For debugging only! + return; } }