diff --git a/documentation/main_test.c b/documentation/main_test.c index d7d3e13..5a3b6ff 100644 --- a/documentation/main_test.c +++ b/documentation/main_test.c @@ -4,19 +4,25 @@ #include "../source/assembler.h" #include "../source/assembler.c" -static unsigned int array [29] = { +#define COUNT (29+24) + +static unsigned int array [COUNT] = { ADC, D64, REG, R1, REG, R2, ADC, D32, REG, R1, MEM, 12, ADC, D16, MEM, 12, REG, R10, ADC, D8, REG, R3, IMM, 0X77, - INC, D16, REG, R0, LOCK + INC, D16, REG, R0, LOCK, + CMOVG, D64, REG, R1, REG, R1, + CMOVG, D64, REG, R1, REG, R9, + CMOVG, D64, REG, R9, REG, R1, + CMOVG, D64, REG, R9, REG, R9 }; int main (void) { unsigned int index; token_array = malloc (144UL * sizeof (* token_array)); - assemble (29, array); + assemble (COUNT, array); printf ("> %u\n", token_count); diff --git a/documentation/test.asm b/documentation/test.asm index 7bbd8e0..b1c1fa9 100644 --- a/documentation/test.asm +++ b/documentation/test.asm @@ -12,7 +12,7 @@ entry $ ; 66 41 81 C1 FF 7F | add r9w 07fffh ; 66 81 05 00 11 00 00 FF 7F | add [x] 07fffh - nop +fff: nop add r9w, [x2] nop add [x2], r9w @@ -354,11 +354,103 @@ entry $ ;~idiv cx nop + nop + nop + +nnn: nop + jmp nnn + nop + jmp fff + nop + jmp rax + nop + jmp rcx + nop + jmp r8 + nop + jmp r9 + nop + jmp word[x2] + nop + jmp qword[x8] nop nop nop + nop + jo nnn + nop + jno fff + nop + jb fff + nop + jae fff + nop + je fff + nop + jne fff + nop + jbe fff + nop + ja fff + nop + js fff + nop + jns fff + nop + jpe fff + nop + jpo fff + nop + jl fff + nop + jge fff + nop + jle fff + nop + jg fff + + nop + nop + nop + + nop + cmovo cx, r9w + nop + cmovg cx, r9w + nop + cmovo ecx, r9d + nop + cmovg ecx, r9d + nop + cmovo rcx, r9 + nop + cmovg rcx, r9 ; 49 0F 4F C9 + nop + xor rcx, rcx + nop + xor r9, rcx;+1 + nop + xor rcx, r9;+4 + nop + xor r9, r9;+1+4 + + nop + nop + nop + + nop + cmovg rcx, rcx; 48 0F 4F C9 + nop + cmovg rcx, r9; 49 0F 4F C9 + nop + cmovg r9, rcx; 4C 0F 4F C9 + nop + cmovg r9, r9; 4D 0F 4F C9 + + nop + nop nop nop diff --git a/source/assembler.c b/source/assembler.c index e634a3e..86d6a01 100644 --- a/source/assembler.c +++ b/source/assembler.c @@ -27,14 +27,28 @@ splint assembler.h: #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; @@ -44,56 +58,94 @@ 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 displacement (form size, + next data) { + /* */ + (void) size; + + place (1, (data >> 24) & 0XFF); + place (1, (data >> 16) & 0XFF); + place (1, (data >> 8) & 0XFF); + place (1, (data >> 0) & 0XFF); +} + +// -- +static void immediate (form size, + next data) { + /* */ + (void) size; + + place (1, (data >> 24) & 0XFF); + place (1, (data >> 16) & 0XFF); + place (1, (data >> 8) & 0XFF); + place (1, (data >> 0) & 0XFF); +} + 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 + + 0X01 * use_new_source + + 0X04 * use_new_destination + 0X08 * use_big_registers)); } +// C0-FF static void build_register_direction (form when, next destination, next source) { + /* */ place (when, (byte) (0XC0 - + 0X01 * (destination % 8) - + 0X08 * (source % 8))); + + 0X01 * (destination & 0X07) + + 0X08 * (source & 0X07))); } +// 05-3D static void build_register_redirection (form when, next direction) { + /* */ place (when, (byte) (0X05 - + 0X08 * (direction % 8))); + + 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 (destination)), - (from == REG) && (upper (source))); + (to == REG) && (upper ((form) destination)), + (from == REG) && (upper ((form) source))); build_constant (from == IMM, size); place (1, (byte) (0X08 * (operation - REGULAR_BEGIN) - + destination % 8 * ((to == REG) && (from == IMM)) + + (destination & 0X07) * ((to == REG) && (from == IMM)) + 0X01 * (size != D8) + 0X02 * ((from == MEM) && (to == REG)) + 0X04 * ((from == IMM) && (to == MEM)) @@ -106,27 +158,30 @@ static void build_regular (operation_index operation, build_register_redirection ((to == MEM) && (from == REG), 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 (destination)), 0); + (to == REG) && (upper ((form) destination)), 0); place (1, (byte) (0XF6 + 0X08 * ((operation == INC) || (operation == DEC)) - + 0X01 * (size != D8))); + + 0X01 * (size != D8))); place (to == REG, (byte) (0XC0 + 0X08 * (operation - IRREGULAR_BEGIN)) - + 0X01 * (destination % 8)); + + 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 @@ -135,6 +190,7 @@ static void build_special_1 (operation_index operation) { 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, @@ -145,10 +201,51 @@ static void build_special_2 (operation_index operation) { 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! +} + next token_count; byte * token_array; -void assemble (next count, next * array) { +void assemble (next count, + next * array) { + /* */ next index; for (index = 0; index < count; ++index) { @@ -171,6 +268,17 @@ void assemble (next count, next * array) { && (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; } } } diff --git a/source/assembler.h b/source/assembler.h index 43bad47..f8a8abc 100644 --- a/source/assembler.h +++ b/source/assembler.h @@ -15,19 +15,30 @@ typedef enum { typedef enum { ADD, OR, ADC, SBB, AND, SUB, XOR, CMP, + /* */ INC, DEC, NOT, NEG, UMUL, IMUL, UDIV, IDIV, + /* */ NOP, RETN, RETF, LEAVE, LOCK, HLT, + /* */ SYSENTER, SYSEXIT, SYSCALL, SYSRET, PAUSE, CPUID, + /* */ ENTER, CALL, IN, OUT, - JMP, JPE, JS, JPO, - JE, JNE, JZ, JNZ, - JA, JNA, JB, JNB, - MOV, CMOVPE, CMOVS, CMOVPO, - CMOVE, CMOVNE, CMOVZ, CMOVNZ, - CMOVA, CMOVNA, CMOVB, CMOVNB, + /* */ + JMP, + JO, JNO, JB, JAE, + JE, JNE, JBE, JA, + JS, JNS, JPE, JPO, + JL, JGE, JLE, JG, + /* */ + MOV, + CMOVO, CMOVNO, CMOVB, CMOVAE, + CMOVE, CMOVNE, CMOVBE, CMOVA, + CMOVS, CMOVNS, CMOVPE, CMOVPO, + CMOVL, CMOVGE, CMOVLE, CMOVG, + /* */ PUSH, POP, BSWAP, TEST, RCL, RCR, ROL, ROR, SHL, SHR, SAL, SAR,