#include "linker.h" #include #include #include #include #include #include #include #include void fasmVariablePrint(FasmVariable variable) { printf(" {name='%.*s',value=0x%lx}\n", (int)(variable.end - variable.begin), variable.begin, variable.value); } void fasmLinkedLinePrint(FasmLinkedLine line) { printf(" {instruction='%s',operands=[\n", FASM_TOKEN_STRINGS[line.instruction]); for (size_t i = 0; i < line.operands_size; ++i) { printf(" 0x%x,\n", line.operands[i]); } printf(" ]}\n"); } void fasmLinkedLinesPrint(FasmLinkedLines lines) { printf("{lines=[\n"); for (size_t i = 0; i < lines.lines_size; ++i) { fasmLinkedLinePrint(lines.lines[i]); } printf("],\ndata=[\n"); for (size_t i = 0; i < lines.data_size; ++i) { printf(" 0x%.2x,\n", lines.data[i]); } printf("],\nvariable=[\n"); for (size_t i = 0; i < lines.variables_size; ++i) { fasmVariablePrint(lines.variables[i]); } printf("]}\n"); } void fasmLinkedLineDeleteInner(FasmLinkedLine line) { free(line.operands); } void fasmLinkedLinesDeleteInner(FasmLinkedLines lines) { for (size_t i = 0; i < lines.lines_size; ++i) { fasmLinkedLineDeleteInner(lines.lines[i]); } free(lines.lines); free(lines.variables); free(lines.data); } FasmLinkedLines fasmLinker(const FasmLines *lines, SourceCode *sourceCode) { FasmLinkedLines linkedLines = { .lines = a404m_malloc(0), .lines_size = 0, .variables = a404m_malloc(0), .variables_size = 0, .data = a404m_malloc(0), .data_size = 0, }; fasmLinesSetVariables(&linkedLines, lines, sourceCode); fasmLinesSetLines(&linkedLines, lines, sourceCode); fasmLinesSetData(&linkedLines, lines, sourceCode); return linkedLines; // RETURN_ERROR: const FasmLinkedLines ERROR = { .lines = NULL, .lines_size = ERROR_SIZE, .variables = NULL, .variables_size = ERROR_SIZE, .data = NULL, .data_size = ERROR_SIZE, }; return ERROR; } void fasmLinesSetVariables(FasmLinkedLines *linkedLines, const FasmLines *lines, SourceCode *sourceCode) { size_t inserted = 0; for (size_t i = 0; i < sourceCode->size; ++i) { const FasmLines linesHolder = lines[i]; for (size_t j = 0; j < linesHolder.lines_size; ++j) { const FasmLine line = lines->lines[j]; if (line.labelBegin != line.labelEnd) { const FasmVariable variable = { .begin = line.labelBegin, .end = line.labelEnd, .value = inserted, }; fasmLinesPushVariable(linkedLines, variable); } inserted += getSizeOfLine(line); } } inserted = 0; for (size_t i = 0; i < sourceCode->size; ++i) { const FasmLines linesHolder = lines[i]; for (size_t j = 0; j < linesHolder.data_size; ++j) { const FasmLine line = lines->data[j]; if (line.labelBegin != line.labelEnd) { const FasmVariable variable = { .begin = line.labelBegin, .end = line.labelEnd, .value = inserted, }; fasmLinesPushVariable(linkedLines, variable); } inserted += getSizeOfLine(line); } } } void fasmLinesSetLines(FasmLinkedLines *linkedLines, const FasmLines *lines, SourceCode *sourceCode) { for (size_t i = 0; i < sourceCode->size; ++i) { const FasmLines linesHolder = lines[i]; for (size_t j = 0; j < linesHolder.lines_size; ++j) { const FasmLine line = lines->lines[j]; fasmLinesPushLine(linkedLines, fasmLinesParseLine(linkedLines, line, sourceCode)); } } } extern void fasmLinesSetData(FasmLinkedLines *linkedLines, const FasmLines *lines, SourceCode *sourceCode) { for (size_t i = 0; i < sourceCode->size; ++i) { const FasmLines linesHolder = lines[i]; for (size_t j = 0; j < linesHolder.data_size; ++j) { const FasmLine line = lines->data[j]; FasmLinkedLine linkedLine = fasmLinesParseLine(linkedLines, line, sourceCode); fasmLinesPushData(linkedLines, linkedLine.operands, linkedLine.operands_size); fasmLinkedLineDeleteInner(linkedLine); } } } FasmLinkedLine fasmLinesParseLine(FasmLinkedLines *linkedLines, FasmLine line, SourceCode *sourceCode) { const FasmLinkedLine linkedLine = { .begin = line.begin, .end = line.end, .instruction = line.instruction, .operands = a404m_malloc(getSizeOfLineOperands(line)), .operands_size = getSizeOfLineOperands(line), }; const size_t elementSize = getSizeOfLineOperandElementSize(line); size_t inserted = 0; for (size_t i = 0; i < line.operands_size; ++i) { const FasmOperand operand = line.operands[i]; if (isOperandString(operand)) { for (char *iter = operand.begin + 1; iter + 1 < operand.end; ++iter) { switch (elementSize) { case 1: ((uint8_t *)linkedLine.operands)[inserted] = *iter; break; case 2: ((uint16_t *)linkedLine.operands)[inserted] = *iter; break; case 4: ((uint32_t *)linkedLine.operands)[inserted] = *iter; break; case 8: ((uint64_t *)linkedLine.operands)[inserted] = *iter; break; } inserted += 1; } } else { switch (elementSize) { case 1: ((uint8_t *)linkedLine.operands)[inserted] = getOperandValue(linkedLines, operand, sourceCode); break; case 2: ((uint16_t *)linkedLine.operands)[inserted] = getOperandValue(linkedLines, operand, sourceCode); break; case 4: ((uint32_t *)linkedLine.operands)[inserted] = getOperandValue(linkedLines, operand, sourceCode); break; case 8: ((uint64_t *)linkedLine.operands)[inserted] = getOperandValue(linkedLines, operand, sourceCode); break; } inserted += 1; } } return linkedLine; } bool fasmLinkerOperandSizeCorrect(FasmToken token, int size) { switch (token) { case FASM_TOKEN_NOOP: return size == 0; case FASM_TOKEN_PUSH8: case FASM_TOKEN_PUSH16: case FASM_TOKEN_PUSH32: case FASM_TOKEN_PUSH64: return size == 1; case FASM_TOKEN_LOAD8: case FASM_TOKEN_LOAD16: case FASM_TOKEN_LOAD32: case FASM_TOKEN_LOAD64: case FASM_TOKEN_POP8: case FASM_TOKEN_POP16: case FASM_TOKEN_POP32: case FASM_TOKEN_POP64: case FASM_TOKEN_DUP8: case FASM_TOKEN_DUP16: case FASM_TOKEN_DUP32: case FASM_TOKEN_DUP64: case FASM_TOKEN_SWAP8: case FASM_TOKEN_SWAP16: case FASM_TOKEN_SWAP32: case FASM_TOKEN_SWAP64: case FASM_TOKEN_DROP8: case FASM_TOKEN_DROP16: case FASM_TOKEN_DROP32: case FASM_TOKEN_DROP64: case FASM_TOKEN_ADD_I8: case FASM_TOKEN_ADD_I16: case FASM_TOKEN_ADD_I32: case FASM_TOKEN_ADD_I64: case FASM_TOKEN_ADD_F32: case FASM_TOKEN_ADD_F64: case FASM_TOKEN_SUB_I8: case FASM_TOKEN_SUB_I16: case FASM_TOKEN_SUB_I32: case FASM_TOKEN_SUB_I64: case FASM_TOKEN_SUB_F32: case FASM_TOKEN_SUB_F64: case FASM_TOKEN_NEG_I8: case FASM_TOKEN_NEG_I16: case FASM_TOKEN_NEG_I32: case FASM_TOKEN_NEG_I64: case FASM_TOKEN_NEG_F32: case FASM_TOKEN_NEG_F64: case FASM_TOKEN_MUL_I8: case FASM_TOKEN_MUL_I16: case FASM_TOKEN_MUL_I32: case FASM_TOKEN_MUL_I64: case FASM_TOKEN_MUL_U8: case FASM_TOKEN_MUL_U16: case FASM_TOKEN_MUL_U32: case FASM_TOKEN_MUL_U64: case FASM_TOKEN_MUL_F32: case FASM_TOKEN_MUL_F64: case FASM_TOKEN_DIV_I8: case FASM_TOKEN_DIV_I16: case FASM_TOKEN_DIV_I32: case FASM_TOKEN_DIV_I64: case FASM_TOKEN_DIV_U8: case FASM_TOKEN_DIV_U16: case FASM_TOKEN_DIV_U32: case FASM_TOKEN_DIV_U64: case FASM_TOKEN_DIV_F32: case FASM_TOKEN_DIV_F64: case FASM_TOKEN_REM_I8: case FASM_TOKEN_REM_I16: case FASM_TOKEN_REM_I32: case FASM_TOKEN_REM_I64: case FASM_TOKEN_REM_U8: case FASM_TOKEN_REM_U16: case FASM_TOKEN_REM_U32: case FASM_TOKEN_REM_U64: case FASM_TOKEN_CAST_I8_I64: case FASM_TOKEN_CAST_I16_I64: case FASM_TOKEN_CAST_I32_I64: case FASM_TOKEN_CAST_I64_I8: case FASM_TOKEN_CAST_I64_I16: case FASM_TOKEN_CAST_I64_I32: case FASM_TOKEN_CAST_F64_I64: case FASM_TOKEN_CAST_I64_F64: case FASM_TOKEN_CAST_U8_U64: case FASM_TOKEN_CAST_U16_U64: case FASM_TOKEN_CAST_U32_U64: case FASM_TOKEN_CAST_U64_U8: case FASM_TOKEN_CAST_U64_U16: case FASM_TOKEN_CAST_U64_U32: case FASM_TOKEN_CAST_F64_U64: case FASM_TOKEN_CAST_U64_F64: case FASM_TOKEN_CAST_F32_F64: case FASM_TOKEN_CAST_F64_F32: case FASM_TOKEN_JUMP: case FASM_TOKEN_JZ_I8: case FASM_TOKEN_JNZ_I8: case FASM_TOKEN_JN_I8: case FASM_TOKEN_JNN_I8: case FASM_TOKEN_JP_I8: case FASM_TOKEN_JNP_I8: case FASM_TOKEN_JZ_I16: case FASM_TOKEN_JNZ_I16: case FASM_TOKEN_JN_I16: case FASM_TOKEN_JNN_I16: case FASM_TOKEN_JP_I16: case FASM_TOKEN_JNP_I16: case FASM_TOKEN_JZ_I32: case FASM_TOKEN_JNZ_I32: case FASM_TOKEN_JN_I32: case FASM_TOKEN_JNN_I32: case FASM_TOKEN_JP_I32: case FASM_TOKEN_JNP_I32: case FASM_TOKEN_JZ_I64: case FASM_TOKEN_JNZ_I64: case FASM_TOKEN_JN_I64: case FASM_TOKEN_JNN_I64: case FASM_TOKEN_JP_I64: case FASM_TOKEN_JNP_I64: case FASM_TOKEN_JZ_F32: case FASM_TOKEN_JNZ_F32: case FASM_TOKEN_JN_F32: case FASM_TOKEN_JNN_F32: case FASM_TOKEN_JP_F32: case FASM_TOKEN_JNP_F32: case FASM_TOKEN_JZ_F64: case FASM_TOKEN_JNZ_F64: case FASM_TOKEN_JN_F64: case FASM_TOKEN_JNN_F64: case FASM_TOKEN_JP_F64: case FASM_TOKEN_JNP_F64: case FASM_TOKEN_ALLOC_HEAP: case FASM_TOKEN_ALLOC_STACK: case FASM_TOKEN_FREE_HEAP: case FASM_TOKEN_GET_STACK_ADDRESS: case FASM_TOKEN_GET_GLOBAL_ADDRESS: case FASM_TOKEN_CALL: case FASM_TOKEN_RET: return size == 0; case FASM_TOKEN_SYSCALL: return size == 1; case FASM_TOKEN_DEFINE_BYTE: case FASM_TOKEN_DEFINE_WORD: case FASM_TOKEN_DEFINE_DWORD: case FASM_TOKEN_DEFINE_QWORD: return size > 1; case FASM_TOKEN_NONE: return false; } fprintf(stderr, "Bad fasm token '%d' at %s:%d", token, __FILE_NAME__, __LINE__); exit(1); } size_t getSizeOfLine(const FasmLine line) { return sizeof(line.instruction) + getSizeOfLineOperands(line); } size_t getSizeOfLineOperands(const FasmLine line) { switch (line.instruction) { case FASM_TOKEN_PUSH8: return 1; case FASM_TOKEN_PUSH16: return 2; case FASM_TOKEN_PUSH32: return 4; case FASM_TOKEN_PUSH64: return 8; case FASM_TOKEN_LOAD8: case FASM_TOKEN_LOAD16: case FASM_TOKEN_LOAD32: case FASM_TOKEN_LOAD64: case FASM_TOKEN_POP8: case FASM_TOKEN_POP16: case FASM_TOKEN_POP32: case FASM_TOKEN_POP64: case FASM_TOKEN_DUP8: case FASM_TOKEN_DUP16: case FASM_TOKEN_DUP32: case FASM_TOKEN_DUP64: case FASM_TOKEN_SWAP8: case FASM_TOKEN_SWAP16: case FASM_TOKEN_SWAP32: case FASM_TOKEN_SWAP64: case FASM_TOKEN_DROP8: case FASM_TOKEN_DROP16: case FASM_TOKEN_DROP32: case FASM_TOKEN_DROP64: case FASM_TOKEN_ADD_I8: case FASM_TOKEN_ADD_I16: case FASM_TOKEN_ADD_I32: case FASM_TOKEN_ADD_I64: case FASM_TOKEN_ADD_F32: case FASM_TOKEN_ADD_F64: case FASM_TOKEN_SUB_I8: case FASM_TOKEN_SUB_I16: case FASM_TOKEN_SUB_I32: case FASM_TOKEN_SUB_I64: case FASM_TOKEN_SUB_F32: case FASM_TOKEN_SUB_F64: case FASM_TOKEN_NEG_I8: case FASM_TOKEN_NEG_I16: case FASM_TOKEN_NEG_I32: case FASM_TOKEN_NEG_I64: case FASM_TOKEN_NEG_F32: case FASM_TOKEN_NEG_F64: case FASM_TOKEN_MUL_I8: case FASM_TOKEN_MUL_I16: case FASM_TOKEN_MUL_I32: case FASM_TOKEN_MUL_I64: case FASM_TOKEN_MUL_U8: case FASM_TOKEN_MUL_U16: case FASM_TOKEN_MUL_U32: case FASM_TOKEN_MUL_U64: case FASM_TOKEN_MUL_F32: case FASM_TOKEN_MUL_F64: case FASM_TOKEN_DIV_I8: case FASM_TOKEN_DIV_I16: case FASM_TOKEN_DIV_I32: case FASM_TOKEN_DIV_I64: case FASM_TOKEN_DIV_U8: case FASM_TOKEN_DIV_U16: case FASM_TOKEN_DIV_U32: case FASM_TOKEN_DIV_U64: case FASM_TOKEN_DIV_F32: case FASM_TOKEN_DIV_F64: case FASM_TOKEN_REM_I8: case FASM_TOKEN_REM_I16: case FASM_TOKEN_REM_I32: case FASM_TOKEN_REM_I64: case FASM_TOKEN_REM_U8: case FASM_TOKEN_REM_U16: case FASM_TOKEN_REM_U32: case FASM_TOKEN_REM_U64: case FASM_TOKEN_CAST_I8_I64: case FASM_TOKEN_CAST_I16_I64: case FASM_TOKEN_CAST_I32_I64: case FASM_TOKEN_CAST_I64_I8: case FASM_TOKEN_CAST_I64_I16: case FASM_TOKEN_CAST_I64_I32: case FASM_TOKEN_CAST_F64_I64: case FASM_TOKEN_CAST_I64_F64: case FASM_TOKEN_CAST_U8_U64: case FASM_TOKEN_CAST_U16_U64: case FASM_TOKEN_CAST_U32_U64: case FASM_TOKEN_CAST_U64_U8: case FASM_TOKEN_CAST_U64_U16: case FASM_TOKEN_CAST_U64_U32: case FASM_TOKEN_CAST_F64_U64: case FASM_TOKEN_CAST_U64_F64: case FASM_TOKEN_CAST_F32_F64: case FASM_TOKEN_CAST_F64_F32: case FASM_TOKEN_JUMP: case FASM_TOKEN_JZ_I8: case FASM_TOKEN_JNZ_I8: case FASM_TOKEN_JN_I8: case FASM_TOKEN_JNN_I8: case FASM_TOKEN_JP_I8: case FASM_TOKEN_JNP_I8: case FASM_TOKEN_JZ_I16: case FASM_TOKEN_JNZ_I16: case FASM_TOKEN_JN_I16: case FASM_TOKEN_JNN_I16: case FASM_TOKEN_JP_I16: case FASM_TOKEN_JNP_I16: case FASM_TOKEN_JZ_I32: case FASM_TOKEN_JNZ_I32: case FASM_TOKEN_JN_I32: case FASM_TOKEN_JNN_I32: case FASM_TOKEN_JP_I32: case FASM_TOKEN_JNP_I32: case FASM_TOKEN_JZ_I64: case FASM_TOKEN_JNZ_I64: case FASM_TOKEN_JN_I64: case FASM_TOKEN_JNN_I64: case FASM_TOKEN_JP_I64: case FASM_TOKEN_JNP_I64: case FASM_TOKEN_JZ_F32: case FASM_TOKEN_JNZ_F32: case FASM_TOKEN_JN_F32: case FASM_TOKEN_JNN_F32: case FASM_TOKEN_JP_F32: case FASM_TOKEN_JNP_F32: case FASM_TOKEN_JZ_F64: case FASM_TOKEN_JNZ_F64: case FASM_TOKEN_JN_F64: case FASM_TOKEN_JNN_F64: case FASM_TOKEN_JP_F64: case FASM_TOKEN_JNP_F64: case FASM_TOKEN_ALLOC_HEAP: case FASM_TOKEN_ALLOC_STACK: case FASM_TOKEN_FREE_HEAP: case FASM_TOKEN_GET_STACK_ADDRESS: case FASM_TOKEN_GET_GLOBAL_ADDRESS: case FASM_TOKEN_CALL: case FASM_TOKEN_RET: case FASM_TOKEN_NOOP: case FASM_TOKEN_SYSCALL: return 0; case FASM_TOKEN_DEFINE_BYTE: case FASM_TOKEN_DEFINE_WORD: case FASM_TOKEN_DEFINE_DWORD: case FASM_TOKEN_DEFINE_QWORD: { size_t elementSize; switch (line.instruction) { case FASM_TOKEN_DEFINE_BYTE: elementSize = 1; break; case FASM_TOKEN_DEFINE_WORD: elementSize = 2; break; case FASM_TOKEN_DEFINE_DWORD: elementSize = 4; break; case FASM_TOKEN_DEFINE_QWORD: elementSize = 8; break; default: } size_t size = 0; for (size_t i = 0; i < line.operands_size; ++i) { const FasmOperand operand = line.operands[i]; if (isOperandString(operand)) { size += (operand.end - operand.begin - 2) * elementSize; } else { size += elementSize; } } return size; } case FASM_TOKEN_NONE: } fprintf(stderr, "Bad fasm token '%d' at %s:%d", line.instruction, __FILE_NAME__, __LINE__); exit(1); } size_t getSizeOfLineOperandElementSize(const FasmLine line) { switch (line.instruction) { case FASM_TOKEN_NOOP: return 0; case FASM_TOKEN_PUSH8: return 1; case FASM_TOKEN_PUSH16: return 2; case FASM_TOKEN_PUSH32: return 4; case FASM_TOKEN_PUSH64: return 8; case FASM_TOKEN_LOAD8: case FASM_TOKEN_LOAD16: case FASM_TOKEN_LOAD32: case FASM_TOKEN_LOAD64: case FASM_TOKEN_POP8: case FASM_TOKEN_POP16: case FASM_TOKEN_POP32: case FASM_TOKEN_POP64: case FASM_TOKEN_DUP8: case FASM_TOKEN_DUP16: case FASM_TOKEN_DUP32: case FASM_TOKEN_DUP64: case FASM_TOKEN_SWAP8: case FASM_TOKEN_SWAP16: case FASM_TOKEN_SWAP32: case FASM_TOKEN_SWAP64: case FASM_TOKEN_DROP8: case FASM_TOKEN_DROP16: case FASM_TOKEN_DROP32: case FASM_TOKEN_DROP64: case FASM_TOKEN_ADD_I8: case FASM_TOKEN_ADD_I16: case FASM_TOKEN_ADD_I32: case FASM_TOKEN_ADD_I64: case FASM_TOKEN_ADD_F32: case FASM_TOKEN_ADD_F64: case FASM_TOKEN_SUB_I8: case FASM_TOKEN_SUB_I16: case FASM_TOKEN_SUB_I32: case FASM_TOKEN_SUB_I64: case FASM_TOKEN_SUB_F32: case FASM_TOKEN_SUB_F64: case FASM_TOKEN_NEG_I8: case FASM_TOKEN_NEG_I16: case FASM_TOKEN_NEG_I32: case FASM_TOKEN_NEG_I64: case FASM_TOKEN_NEG_F32: case FASM_TOKEN_NEG_F64: case FASM_TOKEN_MUL_I8: case FASM_TOKEN_MUL_I16: case FASM_TOKEN_MUL_I32: case FASM_TOKEN_MUL_I64: case FASM_TOKEN_MUL_U8: case FASM_TOKEN_MUL_U16: case FASM_TOKEN_MUL_U32: case FASM_TOKEN_MUL_U64: case FASM_TOKEN_MUL_F32: case FASM_TOKEN_MUL_F64: case FASM_TOKEN_DIV_I8: case FASM_TOKEN_DIV_I16: case FASM_TOKEN_DIV_I32: case FASM_TOKEN_DIV_I64: case FASM_TOKEN_DIV_U8: case FASM_TOKEN_DIV_U16: case FASM_TOKEN_DIV_U32: case FASM_TOKEN_DIV_U64: case FASM_TOKEN_DIV_F32: case FASM_TOKEN_DIV_F64: case FASM_TOKEN_REM_I8: case FASM_TOKEN_REM_I16: case FASM_TOKEN_REM_I32: case FASM_TOKEN_REM_I64: case FASM_TOKEN_REM_U8: case FASM_TOKEN_REM_U16: case FASM_TOKEN_REM_U32: case FASM_TOKEN_REM_U64: case FASM_TOKEN_CAST_I8_I64: case FASM_TOKEN_CAST_I16_I64: case FASM_TOKEN_CAST_I32_I64: case FASM_TOKEN_CAST_I64_I8: case FASM_TOKEN_CAST_I64_I16: case FASM_TOKEN_CAST_I64_I32: case FASM_TOKEN_CAST_F64_I64: case FASM_TOKEN_CAST_I64_F64: case FASM_TOKEN_CAST_U8_U64: case FASM_TOKEN_CAST_U16_U64: case FASM_TOKEN_CAST_U32_U64: case FASM_TOKEN_CAST_U64_U8: case FASM_TOKEN_CAST_U64_U16: case FASM_TOKEN_CAST_U64_U32: case FASM_TOKEN_CAST_F64_U64: case FASM_TOKEN_CAST_U64_F64: case FASM_TOKEN_CAST_F32_F64: case FASM_TOKEN_CAST_F64_F32: case FASM_TOKEN_JUMP: case FASM_TOKEN_JZ_I8: case FASM_TOKEN_JNZ_I8: case FASM_TOKEN_JN_I8: case FASM_TOKEN_JNN_I8: case FASM_TOKEN_JP_I8: case FASM_TOKEN_JNP_I8: case FASM_TOKEN_JZ_I16: case FASM_TOKEN_JNZ_I16: case FASM_TOKEN_JN_I16: case FASM_TOKEN_JNN_I16: case FASM_TOKEN_JP_I16: case FASM_TOKEN_JNP_I16: case FASM_TOKEN_JZ_I32: case FASM_TOKEN_JNZ_I32: case FASM_TOKEN_JN_I32: case FASM_TOKEN_JNN_I32: case FASM_TOKEN_JP_I32: case FASM_TOKEN_JNP_I32: case FASM_TOKEN_JZ_I64: case FASM_TOKEN_JNZ_I64: case FASM_TOKEN_JN_I64: case FASM_TOKEN_JNN_I64: case FASM_TOKEN_JP_I64: case FASM_TOKEN_JNP_I64: case FASM_TOKEN_JZ_F32: case FASM_TOKEN_JNZ_F32: case FASM_TOKEN_JN_F32: case FASM_TOKEN_JNN_F32: case FASM_TOKEN_JP_F32: case FASM_TOKEN_JNP_F32: case FASM_TOKEN_JZ_F64: case FASM_TOKEN_JNZ_F64: case FASM_TOKEN_JN_F64: case FASM_TOKEN_JNN_F64: case FASM_TOKEN_JP_F64: case FASM_TOKEN_JNP_F64: case FASM_TOKEN_ALLOC_HEAP: case FASM_TOKEN_ALLOC_STACK: case FASM_TOKEN_FREE_HEAP: case FASM_TOKEN_GET_STACK_ADDRESS: case FASM_TOKEN_GET_GLOBAL_ADDRESS: case FASM_TOKEN_CALL: case FASM_TOKEN_RET: case FASM_TOKEN_SYSCALL: return 0; case FASM_TOKEN_DEFINE_BYTE: return 1; case FASM_TOKEN_DEFINE_WORD: return 2; case FASM_TOKEN_DEFINE_DWORD: return 4; case FASM_TOKEN_DEFINE_QWORD: return 8; case FASM_TOKEN_NONE: } fprintf(stderr, "Bad fasm token '%d' at %s:%d", line.instruction, __FILE_NAME__, __LINE__); exit(1); } void fasmLinesPushVariable(FasmLinkedLines *linkedLines, FasmVariable variable) { const size_t size = a404m_malloc_usable_size(linkedLines->variables) / sizeof(*linkedLines->variables); if (size == linkedLines->variables_size) { linkedLines->variables = a404m_realloc(linkedLines->variables, (size + size / 2 + 1) * sizeof(*linkedLines->variables)); } linkedLines->variables[linkedLines->variables_size] = variable; linkedLines->variables_size += 1; } void fasmLinesPushLine(FasmLinkedLines *linkedLines, FasmLinkedLine line) { const size_t size = a404m_malloc_usable_size(linkedLines->lines) / sizeof(*linkedLines->lines); if (size == linkedLines->lines_size) { linkedLines->lines = a404m_realloc(linkedLines->lines, (size + size / 2 + 1) * sizeof(*linkedLines->lines)); } linkedLines->lines[linkedLines->lines_size] = line; linkedLines->lines_size += 1; } void fasmLinesPushData(FasmLinkedLines *linkedLines, uint8_t *data, size_t size) { linkedLines->data = a404m_realloc(linkedLines->data, (linkedLines->data_size + size) * sizeof(*linkedLines->data)); memcpy(linkedLines->data + linkedLines->data_size, data, size); linkedLines->data_size += size; } FasmVariable fasmLinesGetVariable(const FasmLinkedLines *linkedLines, char const *nameBegin, char const *nameEnd) { const size_t size = nameEnd - nameBegin; for (size_t i = 0; i < linkedLines->variables_size; ++i) { const FasmVariable variable = linkedLines->variables[i]; const size_t variable_str_size = variable.end - variable.begin; if (size == variable_str_size && strncmp(variable.begin, nameBegin, size) == 0) { return variable; } } FasmVariable ERROR = { .begin = NULL, .end = NULL, .value = 0, }; return ERROR; } bool isOperandString(FasmOperand operand) { return *(operand.begin) == '"'; } uint64_t getOperandValue(FasmLinkedLines *linkedLines, FasmOperand operand, SourceCode *sourceCode) { char c = *(operand.begin); if (c == '"') { fprintf(stderr, "It shoulden't be here"); exit(1); } else if (c == '0') { ++(operand.begin); if (operand.begin == operand.end) { return 0; } c = *(operand.begin); if (c == 'x') { return hexStrToInt(operand.begin + 1, operand.end, sourceCode); } else if (c == 'b') { return binStrToInt(operand.begin + 1, operand.end, sourceCode); } else { return strToInt(operand.begin + 1, operand.end, sourceCode); } } else if (c == '-') { ++(operand.begin); if (operand.begin == operand.end) { printError("Expected value after -", sourceCode, operand.begin, operand.end); exit(1); } c = *(operand.begin); if (c == '0') { ++(operand.begin); if (operand.begin == operand.end) { return 0; } c = *(operand.begin); if (c == 'x') { return -hexStrToInt(operand.begin + 1, operand.end, sourceCode); } else if (c == 'b') { return -binStrToInt(operand.begin + 1, operand.end, sourceCode); } else { return -strToInt(operand.begin + 1, operand.end, sourceCode); } } } else if ('0' <= c && c <= '9') { return strToInt(operand.begin, operand.end, sourceCode); } else { const FasmVariable variable = fasmLinesGetVariable(linkedLines, operand.begin, operand.end); if (variable.begin == NULL) { printError("Label '%.*s' not found", sourceCode, operand.begin, operand.end, (int)(operand.end - operand.begin), operand.begin); exit(1); } return variable.value; } printError("Should not come here %s:%d", sourceCode, operand.begin, operand.end, __FILE_NAME__, __LINE__); exit(1); } uint64_t strToInt(const char *begin, const char *end, SourceCode *sourceCode) { uint64_t result = 0; for (char const *iter = begin; iter < end; ++iter) { const char c = *iter; result *= 10; if ('0' <= c && c <= '9') { result += c - '0'; } else { printError("Unexpected character", sourceCode, iter, iter + 1); exit(1); } } return result; } uint64_t hexStrToInt(const char *begin, const char *end, SourceCode *sourceCode) { uint64_t result = 0; for (char const *iter = begin; iter < end; ++iter) { const char c = *iter; result *= 16; if ('0' <= c && c <= '9') { result += c - '0'; } else if ('A' <= c && c < 'F') { result += c - 'A' + 10; } else if ('a' <= c && c < 'f') { result += c - 'a' + 10; } else { printError("Unexpected character", sourceCode, iter, iter + 1); exit(1); } } return result; } uint64_t binStrToInt(const char *begin, const char *end, SourceCode *sourceCode) { uint64_t result = 0; for (char const *iter = begin; iter < end; ++iter) { const char c = *iter; result *= 2; if ('0' <= c && c <= '1') { result += c - '0'; } else { printError("Unexpected character", sourceCode, iter, iter + 1); exit(1); } } return result; }