#include "assembler.h" #include /* gcc -c -ansi -Wall -Wextra -Wpedantic -Werror: -- warns about trailing comma in enumerations. -- kept because of chad coding standard. -- unused functions for now, obviously... clang -c -ansi -Weverything -Werror: -- exactly same warnings as with gcc above. splint -fcnuse +boolint +charint assembler.c: -- we obviously ignore unused functions for now. -- we assume bool is int, which is true. -- we assume char is int, which is true. -- assembler.c:167:13: Function fabs shadows outer declaration -- ^ function from , which we don't even use. splint assembler.h: -- no warnings at all. */ #define REGULAR_BEGIN (ADD) #define REGULAR_END (CMP) #define IRREGULAR_BEGIN (INC) #define IRREGULAR_END (IDIV) #define SPECIAL_1_BEGIN (NOP) #define SPECIAL_1_END (HLT) #define SPECIAL_2_BEGIN (SYSENTER) #define SPECIAL_2_END (CPUID) #define JUMP_IF_BEGIN (JO) #define JUMP_IF_END (JG) #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) // Regulates displacement, immediate, label, variable, constant, string data. static next * empty_from; static next * empty_to; static next * imbue_with; static next * imbue_size; // Main function. static void place (form when, byte data) { /* */ token_array [token_count] = data; token_count += (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)); } static form front (form data) { return ((data >= 4) && (data <= 7)); } static form valid (form data) { return ((data >= 0) && (data <= 15)); } 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 (1); /* DO NOT CHANGE YET! */ } static form near (next label) { return (0); /* DO NOT CHANGE YET! */ } static void build_short_prefix (form when) { place (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, (byte) (0X40 + 0X01 * use_new_destination + 0X04 * use_new_source + 0X08 * use_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))); } // 05-3D static void build_register_redirection (form when, next direction) { /* */ place (when, (byte) (0X05 + 0X08 * (direction & 0X07))); } // 80/81 static void build_constant (form when, size_index size) { /* */ place (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) { /* */ build_short_prefix (size == D16); build_long_prefix (size == D64, (to == REG) && (upper ((form) destination)), (from == REG) && (upper ((form) source))); // 40>front place ((size == D8) && (to == REG) && (from == REG) && ((front (destination) && lower (source)) || (lower (destination) && front (source))), (byte) 0X40); build_constant (from == IMM, size); place (1, (byte) (0X08 * (operation - REGULAR_BEGIN) + (destination & 0X07) * ((to == REG) && (from == IMM)) + 0X01 * ((to == MEM) && (from == IMM) && (size == D8)) // - 0X01 * ((to == REG) && (from == IMM)) // + 0X01 * (size != D8) + 0X02 * ((to == REG) && (from == MEM)) + 0X04 * ((to == MEM) && (from == IMM)) + 0XC0 * ((to == REG) && (from == IMM)))); build_register_direction ((to == REG) && (from == REG), destination, source); 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); } // 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) { /* */ build_short_prefix (size == D16); build_long_prefix (size == D64, (to == REG) && (upper ((form) destination)), 0); place (1, (byte) (0XF6 + 0X08 * ((operation == INC) || (operation == DEC)) + 0X01 * (size != D8))); place (to == REG, (byte) (0XC0 + 0X08 * (operation - IRREGULAR_BEGIN)) + 0X01 * (destination & 0X07)); place (to == MEM, (byte) (0X05 + 0X08 * (operation - IRREGULAR_BEGIN))); } // SPECIAL_1_BEGIN-SPECIAL_1_END static void build_special_1 (operation_index operation) { const byte data [1 * SPECIAL_1_COUNT] = { 0X90, 0XC3, 0XCB, 0XC9, 0XF0, 0XF4 }; place (1, data [operation - SPECIAL_1_BEGIN]); } // SPECIAL_2_BEGIN-SPECIAL_2_END static void build_special_2 (operation_index operation) { 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]); } // 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! */ 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)); //~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) { /* */ 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)); 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! } // SPECIAL! static void build_jump (size_index size, type_index to, next destination) { /* */ place ((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); //~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) { /* */ 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))); build_register_redirection ((to == REG) && (from == MEM), destination); build_register_redirection ((to == MEM) && (from == REG), source); place ((to == REG) && (from == IMM), (byte) (0XB0 + 0X08 * (size != D8) + 0X01 * (destination & 0X07))); place ((to == MEM) && (from == IMM), (byte) (0XC6 + (size != D8))); place ((to == MEM) && (from == IMM), (byte) (0X05)); 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); } next token_count = 0; byte * token_array = NULL; int error_empty_array = 0; void assemble (next count, next * array) { /* */ next index; if ((count == 0) || (array == NULL)) { error_empty_array = 1; return; } for (index = 0; index < count; ++index) { if ((array [index] >= REGULAR_BEGIN) && (array [index] <= REGULAR_END)) { build_regular (array [index + 0], array [index + 1], array [index + 2], array [index + 3], array [index + 4], array [index + 5]); index += 5; } else if ((array [index] >= IRREGULAR_BEGIN) && (array [index] <= IRREGULAR_END)) { build_irregular (array [index + 0], array [index + 1], array [index + 2], array [index + 3]); index += 3; } else if ((array [index] >= SPECIAL_1_BEGIN) && (array [index] <= SPECIAL_1_END)) { build_special_1 (array [index + 0]); index += 0; } else if ((array [index] >= SPECIAL_2_BEGIN) && (array [index] <= SPECIAL_2_END)) { build_special_2 (array [index + 0]); index += 0; } else if ((array [index] >= JUMP_IF_BEGIN) && (array [index] <= JUMP_IF_END)) { build_jump_if (array [index + 0], array [index + 1], array [index + 2]); index += 2; } else if ((array [index] >= MOVE_IF_BEGIN) && (array [index] <= MOVE_IF_END)) { build_move_if (array [index + 0], array [index + 1], array [index + 2], array [index + 3], array [index + 4], array [index + 5]); index += 5; } else if (array [index] == JMP) { build_jump (array [index + 1], array [index + 2], array [index + 3]); index += 3; } else if (array [index] == MOV) { build_move (array [index + 1], array [index + 2], array [index + 3], array [index + 4], array [index + 5]); index += 5; } else { exit (EXIT_FAILURE); // For debugging only! } } }