From 4bcb50865cb022c70d5b542826f128398ce2c4cc Mon Sep 17 00:00:00 2001 From: ALittlePatate Date: Mon, 22 Jan 2024 22:24:40 +0100 Subject: [PATCH] add: arrays --- examples/array.pasm | 37 +++++++++++ msvc/interpreter.vcxproj.user | 17 ++++- src/api.c | 12 +++- src/api.h | 2 + src/debug.c | 14 +++- src/instructions.c | 12 ++++ src/interpreter_states.c | 118 ++++++++++++++++++++++++++++++++++ src/interpreter_states.h | 10 +++ src/pasm.c | 12 +++- 9 files changed, 228 insertions(+), 6 deletions(-) create mode 100644 examples/array.pasm diff --git a/examples/array.pasm b/examples/array.pasm new file mode 100644 index 0000000..c3ae3d9 --- /dev/null +++ b/examples/array.pasm @@ -0,0 +1,37 @@ +; Simple program that showcases the usage of string and number arrays + +set msg "hello, world !\0" +set arr 1, 2, 3, 4, 5 + +show_arr: +mov a1, arr +mov a2, 0 + +loop2: +cmp a2, 5 +jne 1 +end + +add a2, 1 +push *a1 +push 2 +call put +add a1, 8 +jmp loop2 + +main: +mov a1, msg ; msg is a char * + +loop: +cmp *a1, 0 +jne 1 +jmp show_arr + +push *a1 +push 1 +call put + +add a1, 8 ; little ptr theory here, as the stack is of type long long + ; to go to the next value you have to add sizeof(long long) to the ptr + ; so you need to add 8 +jmp loop \ No newline at end of file diff --git a/msvc/interpreter.vcxproj.user b/msvc/interpreter.vcxproj.user index 88a5509..f621c28 100644 --- a/msvc/interpreter.vcxproj.user +++ b/msvc/interpreter.vcxproj.user @@ -1,4 +1,19 @@  - + + ../examples/array.pasm + WindowsLocalDebugger + + + ../examples/array.pasm + WindowsLocalDebugger + + + ../examples/array.pasm + WindowsLocalDebugger + + + ../examples/array.pasm + WindowsLocalDebugger + \ No newline at end of file diff --git a/src/api.c b/src/api.c index 9e35933..c0946b3 100644 --- a/src/api.c +++ b/src/api.c @@ -11,8 +11,14 @@ extern int dprintf(int stream, const char *format, ...); #endif +void api_get_data() { + static const char dat[] = "Hello, World !"; + + state->registers->eax = (long long)dat; +} + void api_put() { - int mode = state->STACK[state->STACK_IDX--]; // 1 for char, 2 for num + int mode = (int)state->STACK[state->STACK_IDX--]; // 1 for char, 2 for num if (mode != 1 && mode != 2) return; int f = fstream; @@ -25,7 +31,7 @@ void api_put() { #endif if (mode == 1) { - char c = state->STACK[state->STACK_IDX--]; + char c = (char)state->STACK[state->STACK_IDX--]; if (c == '\0') c = ' '; dprintf(f, "%c", c); //using printf and not write because of the buffer @@ -37,7 +43,7 @@ void api_put() { void api_getasynckeystate() { #ifdef _WIN32 - state->registers->eax = GetAsyncKeyState(state->STACK[state->STACK_IDX--]); + state->registers->eax = GetAsyncKeyState((int)state->STACK[state->STACK_IDX--]); #else state->STACK_IDX--; state->registers->eax = 1; diff --git a/src/api.h b/src/api.h index 63967b8..ea7e96b 100644 --- a/src/api.h +++ b/src/api.h @@ -1,11 +1,13 @@ #pragma once #include "instructions.h" +void api_get_data(); void api_put(); void api_getasynckeystate(); static const command_t api_map[] = { {.command = "put", .fptr = api_put}, + {.command = "get_data", .fptr = api_get_data}, {.command = "GetAsyncKeyState", .fptr = api_getasynckeystate}, {.command = NULL, .fptr = NULL} diff --git a/src/debug.c b/src/debug.c index c4f6c7c..2118c2a 100644 --- a/src/debug.c +++ b/src/debug.c @@ -28,12 +28,23 @@ void show_stack() { void show_labels() { printf("\n\n-----LABELS-----\n"); - printf("format:\tlabel|line"); + printf("format:\tlabel|line\n"); for (int i = 0; i < state->num_labels; i++) printf("%s|%d\n", state->labels[i], state->labels_values[i]); printf("\n\n-----LABELS-----\n"); } +void show_arrays() { + printf("\n\n-----ARRAYS-----\n"); + for (int i = 0; i < state->num_arrays; i++) { + printf("%s: ", state->ARRAYS_NAME[i]); + for (int j = 0; j < 20; j++) + printf("%lld ", state->ARRAYS_VALUES[i][j]); + printf("...\n"); + } + printf("\n\n-----ARRAYS-----\n"); +} + void show_breakpoints(int *bp) { printf("---Breakpoints---\n"); for (int i = 0; bp[i] != 0 && i < 255; i++) { @@ -48,6 +59,7 @@ void show_states() { show_registers(); show_labels(); show_stack(); + show_arrays(); printf("\n\n--------PASM STATE--------\n"); } diff --git a/src/instructions.c b/src/instructions.c index 87dc5d6..a40c3c5 100644 --- a/src/instructions.c +++ b/src/instructions.c @@ -5,9 +5,18 @@ #include #include +bool is_array(char* arg) { + for (int i = 0; i < state->num_arrays; i++) + if (strcmp(state->ARRAYS_NAME[i], arg) == 0) + return true; + return false; +} + bool is_reg(char* arg) { if (arg[0] == '&' || arg[0] == '*') ++arg; + if (is_array(arg)) + return true; return (strcmp(arg, "eax") == 0) || (((arg[0] == 'a' && ('1' <= arg[1] && arg[1] <= '9'))) && strlen(arg) == 2); } @@ -38,6 +47,9 @@ bool check_args(s_arguments *args, int num_in_first, int num_args) { long long* get_reg(char* reg_char) { if (reg_char[0] == '&' || reg_char[0] == '*') ++reg_char; + for (int i = 0; i < state->num_arrays; i++) + if (strcmp(state->ARRAYS_NAME[i], reg_char) == 0) + return &state->ARRAYS_VALUES[i]; switch (reg_char[1]) { case '1' : return &state->registers->a1; diff --git a/src/interpreter_states.c b/src/interpreter_states.c index af96d42..4e01bd9 100644 --- a/src/interpreter_states.c +++ b/src/interpreter_states.c @@ -45,6 +45,7 @@ int init_state() { memset(state->labels_values, 0, sizeof(int) * MAX_LABELS); memset(state->RET_STACK, -1, sizeof(int) * STACK_SIZE); memset(state->STACK, 0, sizeof(long long) * STACK_SIZE); + state->num_arrays = 0; state->RET_STACK_IDX = -1; state->STACK_IDX = -1; state->last_stack_code = STACK_OK; @@ -59,6 +60,15 @@ void free_state() { } free(state->labels); free(state->labels_values); + + for (int j = 0; j < state->num_arrays; j++) { + if (state->ARRAYS_NAME[j]) + free(state->ARRAYS_NAME[j]); + if (state->ARRAYS_VALUES[j]) + free(state->ARRAYS_VALUES[j]); + } + free(state->ARRAYS_NAME); + free(state->ARRAYS_VALUES); free(state->registers); free(state->args->arg1); free(state->args->arg2); @@ -105,6 +115,114 @@ LABEL_ERR add_label(char *label, int line) { return LABEL_OK; } +ARRAY_ERR add_array(char* line) { +#ifdef _WIN32 + char *line_copy = _strdup(line); +#else + char *line_copy = strdup(line); +#endif + if (strncmp(line, "set", 3) != 0) { + free(line_copy); + return ARRAY_NOT_AN_ARRAY; + } + char *ptr = strtok(line_copy, " "); //set + ptr = strtok(NULL, " "); //array name + if (ptr == NULL || strlen(line) <= (4 + strlen(ptr))) { + free(line_copy); + return ARRAY_ERROR; + } + + char **temp = realloc(state->ARRAYS_NAME, (state->num_arrays + 1) * sizeof(char*)); + if (temp == NULL) { + dprintf(fstream, "Error allocating memory.\n"); + return ARRAY_ERROR; + } + state->ARRAYS_NAME = temp; +#ifdef _WIN32 + state->ARRAYS_NAME[state->num_arrays] = _strdup(ptr); +#else + state->ARRAYS_NAME[state->num_arrays] = strdup(ptr); +#endif + ptr += strlen(ptr) + 1; //getting the data in the array, data is data after all + if (ptr == NULL || ptr[0] == ' ' || ptr[0] == '\0') { + free(line_copy); + return ARRAY_ERROR; + } + + char* start_of_values = ptr; + int array_size = 0; + long long *arr = NULL; + if (ptr[0] == '"') { + ++ptr; + while (*ptr++ != '"') { + if (*ptr == '\0') { + free(line_copy); + return ARRAY_ERROR; //" is never closed + } + ++array_size; + } + long long *tmp = realloc(arr, array_size * sizeof(long long)); + if (tmp == NULL || array_size == 0) { + dprintf(fstream, "Error allocating memory.\n"); + return ARRAY_ERROR; + } + arr = tmp; + memset(arr, 0, array_size); + long long **temp = realloc(state->ARRAYS_VALUES, (state->num_arrays + 1) * sizeof(long long*)); + if (temp == NULL) { + dprintf(fstream, "Error allocating memory.\n"); + return ARRAY_ERROR; + } + state->ARRAYS_VALUES = temp; + ptr = start_of_values; + int i = 0; + ++ptr; + while (*ptr != '"') { + if (*ptr == '\0' || i >= array_size) { + free(line_copy); + return ARRAY_ERROR; //" is never closed + } + if (strncmp(ptr, "\\0", 2) == 0) { + arr[i++] = 0; + break; + } + arr[i++] = (long long)* ptr++; + } + state->ARRAYS_VALUES[state->num_arrays++] = arr; + return ARRAY_OK; + } + ptr = strtok(ptr, ","); + while (ptr != NULL) { + array_size++; + ptr = strtok(NULL, ","); + } + long long *tmp2 = realloc(arr, array_size * sizeof(long long)); + if (tmp2 == NULL || array_size == 0) { + dprintf(fstream, "Error allocating memory.\n"); + return ARRAY_ERROR; + } + arr = tmp2; + memset(arr, 0, array_size); + long long **temp2 = realloc(state->ARRAYS_VALUES, (state->num_arrays + 1) * sizeof(long long*)); + if (temp2 == NULL) { + dprintf(fstream, "Error allocating memory.\n"); + return ARRAY_ERROR; + } + state->ARRAYS_VALUES = temp2; + ptr = line + 4 + strlen(state->ARRAYS_NAME[state->num_arrays]) + 1; //leave me alone i'm tired + ptr = strtok(ptr, ","); + int j = 0; + while (ptr != NULL && j < array_size) { + if (ptr[0] == ' ') + ++ptr; + arr[j++] = atoi(ptr); + ptr = strtok(NULL, ","); + } + state->ARRAYS_VALUES[state->num_arrays++] = arr; + free(line_copy); + return ARRAY_OK; +} + char *extract_arg(char *ptr, int a) { char *arg = 0; char *ptr2 = strstr(ptr, ";"); diff --git a/src/interpreter_states.h b/src/interpreter_states.h index c49f018..850d6a9 100644 --- a/src/interpreter_states.h +++ b/src/interpreter_states.h @@ -48,6 +48,9 @@ typedef struct t_state { int RET_STACK_IDX; int STACK_IDX; long long STACK[STACK_SIZE]; + char** ARRAYS_NAME; + int num_arrays; + long long **ARRAYS_VALUES; int last_jmp_code; stack_codes last_stack_code; cmp_return_codes last_cmp_code; @@ -63,9 +66,16 @@ typedef enum E_LABEL_ERR { LABEL_ERROR } LABEL_ERR; +typedef enum E_ARRAY_ERR { + ARRAY_OK, + ARRAY_ERROR, + ARRAY_NOT_AN_ARRAY +} ARRAY_ERR; + int init_state(); void free_state(); void set_exit_state(int exit_state); int get_exit_state(); LABEL_ERR add_label(char *label, int line); +ARRAY_ERR add_array(char *line); int parse_arguments(char *args); diff --git a/src/pasm.c b/src/pasm.c index 4e689c6..f653b8f 100644 --- a/src/pasm.c +++ b/src/pasm.c @@ -105,12 +105,22 @@ int pasm_run_script(const char *filename, char **file, size_t lines, int _fstrea #else char *line = strdup(file[state->curr_line]); #endif - if (line[0] == ';' || line[0] == '\0') { + if (line[0] == ';' || line[0] == '\0' || line[0] == '\t') { free(line); continue; } const command_t *com = find_command(command_map, strtok(line, " ")); if (com == NULL || com->fptr == NULL) { + ARRAY_ERR err = add_array(file[state->curr_line]); + if (err == ARRAY_OK) + continue; + if (err == ARRAY_ERROR) { + show_error(state->curr_line, file[state->curr_line]); + dprintf(fstream, "%s\n", "bad syntax in array definition"); + set_exit_state(-1); + free(line); + break; + } if (file[state->curr_line][strlen(line) - 1] != ':') { show_error(state->curr_line, file[state->curr_line]); dprintf(fstream, "%s \"%s\"\n", "unknown expression", strtok(file[state->curr_line], " "));