From a7817262a07202698063e68bcc1e694825a04e2b Mon Sep 17 00:00:00 2001 From: Tomas 'ZeXx86' Jedrzejek Date: Wed, 22 Oct 2008 19:45:04 +0200 Subject: [PATCH] zasm assembly compiler support next instruction (jmp; inc; mov 32bit, 32bit; hlt) and was improved; system call with id 4 (sleep) was rewrited to non-blocking in meaning - not block a other processes --- apps/zasm/README | 14 +++ apps/zasm/main.c | 10 +- apps/zasm/source.c | 257 ++++++++++++++++++++++++++++++++++++--------- apps/zasm/source.h | 4 +- apps/zasm/src | 19 +++- kernel/.config | 2 +- kernel/arch/i386/syscall.c | 6 +- 7 files changed, 256 insertions(+), 56 deletions(-) create mode 100644 apps/zasm/README diff --git a/apps/zasm/README b/apps/zasm/README new file mode 100644 index 0000000..2f914ad --- /dev/null +++ b/apps/zasm/README @@ -0,0 +1,14 @@ +Description: Assembly compiler and linker +Info: Easy assembler specially writed for ZeX/OS, binary files are generated for unix-like 32bit platforms +Compiling: call "make" for ZeX/OS compatibile system + call "make linux" for Linux compatibile system + +License: GNU/GPL3 +Author: ZeXx86 + +Syntax: +exec zasm + +Test: +exec zasm src /usr/bin +exec /usr/bin diff --git a/apps/zasm/main.c b/apps/zasm/main.c index 01df87e..bf14c44 100644 --- a/apps/zasm/main.c +++ b/apps/zasm/main.c @@ -17,6 +17,7 @@ */ #include +#include #include "source.h" #include "buffer.h" @@ -35,16 +36,21 @@ int param (int argc, char **argv) buffer_init (); source_init (); - char *source = source_open (argv[1]); + unsigned size; + + char *source = source_open (argv[1], &size); if (!source) return 0; - if (!source_parse (source, 512)) + if (!source_parse (source, size)) return 0; buffer_write (argv[2]); + free (source); + free (buffer_get ()); + return 1; } diff --git a/apps/zasm/source.c b/apps/zasm/source.c index abb356c..a215d0f 100644 --- a/apps/zasm/source.c +++ b/apps/zasm/source.c @@ -62,7 +62,7 @@ int var_create (char type, char *name, unsigned len, void *address, unsigned lin var->name[len] = '\0'; var->address = address; - var->line = 0; + var->offset = 0; /* add into list */ var->next = &var_list; @@ -217,60 +217,114 @@ int source_parse (char *source, unsigned size) unsigned char reg = 0; - if (paramreg[0] == 'e' && paramreg[1] == 'a' && paramreg[2] == 'x') - reg = 0xb8; // eax - else if (paramreg[0] == 'e' && paramreg[1] == 'b' && paramreg[2] == 'x') - reg = 0xbb; // ebx - else if (paramreg[0] == 'e' && paramreg[1] == 'c' && paramreg[2] == 'x') - reg = 0xb9; // ecx - else if (paramreg[0] == 'e' && paramreg[1] == 'd' && paramreg[2] == 'x') - reg = 0xba; // edx + if (paramval[0] != 'e') { /* MOV 8bit */ + if (paramreg[0] == 'e' && paramreg[1] == 'a' && paramreg[2] == 'x') + reg = 0xb8; // eax + else if (paramreg[0] == 'e' && paramreg[1] == 'b' && paramreg[2] == 'x') + reg = 0xbb; // ebx + else if (paramreg[0] == 'e' && paramreg[1] == 'c' && paramreg[2] == 'x') + reg = 0xb9; // ecx + else if (paramreg[0] == 'e' && paramreg[1] == 'd' && paramreg[2] == 'x') + reg = 0xba; // edx + + buffer_copy (bin_pos, (void *) ®, 1); + bin_pos ++; - buffer_copy (bin_pos, (void *) ®, 1); - bin_pos ++; + /* Let's convert parameter to binary number */ + if (paramval[0] == '\'') { + if (val_len < 3) { + printf ("ERROR -> wrong parameter syntax - %d != 3, line: %d\n", val_len, line); + return 0; + } - /* Let's convert parameter to binary number */ - if (paramval[0] == '\'') { - if (val_len < 3) { - printf ("ERROR -> wrong parameter syntax - %d != 3, line: %d\n", val_len, line); - return 0; - } + if (paramval[2] != '\'' || paramval[1] == '\'') { + printf ("ERROR -> wrong parameter syntax, line: %d\n", line); + return 0; + } - if (paramval[2] != '\'' || paramval[1] == '\'') { - printf ("ERROR -> wrong parameter syntax, line: %d\n", line); - return 0; - } + int c = paramval[1]; + //printf ("mov val char = %c\n", c); - int c = paramval[1]; - //printf ("mov val char = %c\n", c); + buffer_copy (bin_pos, (void *) &c, sizeof (int)); + bin_pos += sizeof (int); - buffer_copy (bin_pos, (void *) &c, sizeof (int)); - bin_pos += sizeof (int); + } else if (paramval[0] == '0' && paramval[1] == 'x') { + char *endptr, *str = paramval+2; - } else if (paramval[0] == '0' && paramval[1] == 'x') { - char *endptr, *str = paramval+2; + long val = strtol (str, &endptr, 16); - long val = strtol (str, &endptr, 16); + //printf ("mov val hexa = %d\n", val); - //printf ("mov val hexa = %d\n", val); - - buffer_copy (bin_pos, (void *) &val, sizeof (int)); - bin_pos += sizeof (int); - } else { - unsigned x; - for (x = 0; x < val_len-1; x ++) { - if (!(paramval[x] >= '0' && paramval[x] <= '9')) { - printf ("ERROR -> wrong parameter syntax - only numbers are allowed, line: %d\n", line); - return 0; + buffer_copy (bin_pos, (void *) &val, sizeof (int)); + bin_pos += sizeof (int); + } else { + unsigned x; + for (x = 0; x < val_len-1; x ++) { + if (!(paramval[x] >= '0' && paramval[x] <= '9')) { + printf ("ERROR -> wrong parameter syntax - only numbers are allowed, line: %d\n", line); + return 0; + } } + + int num = atoi (paramval); + + //printf ("mov val digit = %d\n", num); + + buffer_copy (bin_pos, (void *) &num, sizeof (int)); + bin_pos += sizeof (int); + } - int num = atoi (paramval); + } else { /*MOV 32bit */ + + reg = 0x89; // 32bit + + buffer_copy (bin_pos, (void *) ®, 1); + bin_pos ++; + + unsigned char regb = 0; + + if (!strncmp (paramreg, "eax", 3)) { + if (!strncmp (paramval, "eax", 3)) + regb = 0xc0; + else if (!strncmp (paramval, "ebx", 3)) + regb = 0xd8; + else if (!strncmp (paramval, "ecx", 3)) + regb = 0xc8; + else if (!strncmp (paramval, "edx", 3)) + regb = 0xd0; + } else if (!strncmp (paramreg, "ebx", 3)) { + if (!strncmp (paramval, "eax", 3)) + regb = 0xc3; + else if (!strncmp (paramval, "ebx", 3)) + regb = 0xdb; + else if (!strncmp (paramval, "ecx", 3)) + regb = 0xcb; + else if (!strncmp (paramval, "edx", 3)) + regb = 0xd3; + } else if (!strncmp (paramreg, "ecx", 3)) { + if (!strncmp (paramval, "eax", 3)) + regb = 0xc1; + else if (!strncmp (paramval, "ebx", 3)) + regb = 0xd9; + else if (!strncmp (paramval, "ecx", 3)) + regb = 0xc9; + else if (!strncmp (paramval, "edx", 3)) + regb = 0xd1; + } else if (!strncmp (paramreg, "edx", 3)) { + if (!strncmp (paramval, "eax", 3)) + regb = 0xc2; + else if (!strncmp (paramval, "ebx", 3)) + regb = 0xda; + else if (!strncmp (paramval, "ecx", 3)) + regb = 0xca; + else if (!strncmp (paramval, "edx", 3)) + regb = 0xd2; + } - //printf ("mov val digit = %d\n", num); + buffer_copy (bin_pos, (void *) ®b, 1); + bin_pos ++; - buffer_copy (bin_pos, (void *) &num, sizeof (int)); - bin_pos += sizeof (int); } line ++; @@ -325,6 +379,88 @@ int source_parse (char *source, unsigned size) continue; } + /* JMP */ + if (!strncmp ("jmp ", source+i, 4)) { + unsigned v = size-i-4; + char *param = source_param (source+i+4, &v); + + if (!param) { + printf ("ERROR -> !param\n"); + return 0; + } + + i += source_nextline (source+i, size-i); + + unsigned char jmp = 0xeb; // jmp + buffer_copy (bin_pos, (void *) &jmp, 1); + bin_pos ++; + + param[v] = '\0'; + + var_t *var = var_find (param); + + if (!var) { + printf ("ERROR -> unknown variable '%s', line %d\n", source+i, line); + return 0; + } + + unsigned diff = (bin_pos - var->offset); + + if (diff > 0xff) { + printf ("ERROR -> it is not 'near jump', line %d\n", line); + return 0; + } + + unsigned char val = 0xff - diff; + + buffer_copy (bin_pos, (void *) &val, 1); + bin_pos ++; + + printf ("jmp: %s\n", param); + + line ++; + continue; + } + + /* INC */ + if (!strncmp ("inc ", source+i, 4)) { + unsigned v = size-i-4; + char *param = source_param (source+i+4, &v); + + if (!param) { + printf ("ERROR -> !param\n"); + return 0; + } + + i += source_nextline (source+i, size-i); + + param[v] = '\0'; + + if (v < 2) { + printf ("ERROR -> inc: bad register name '%s', line %d\n", param, line); + return 0; + } + + unsigned char reg = 0; + + if (!strncmp (param, "eax", 3)) + reg = 0x40; + else if (!strncmp (param, "ebx", 3)) + reg = 0x43; + else if (!strncmp (param, "ecx", 3)) + reg = 0x41; + else if (!strncmp (param, "edx", 3)) + reg = 0x42; + + buffer_copy (bin_pos, (void *) ®, 1); + bin_pos ++; + + printf ("inc: %s\n", param); + + line ++; + continue; + } + /* RET */ if (!strncmp ("ret", source+i, 3)) { if (!function_curr) { @@ -346,6 +482,18 @@ int source_parse (char *source, unsigned size) continue; } + /* HLT */ + if (!strncmp ("hlt", source+i, 3)) { + unsigned char hlt = 0xf4; + buffer_copy (bin_pos, (void *) &hlt, 1); + bin_pos ++; + + i += source_nextline (source+i, size-i); + + line ++; + continue; + } + if ((source[i] >= 'a' && source[i] <= 'z') || (source[i] >= 'A' && source[i] <= 'Z')) { unsigned y; @@ -363,6 +511,8 @@ int source_parse (char *source, unsigned size) printf ("Function '%s' on line %d\n", var->name, line); + var->offset = bin_pos; + function_curr = var; // set current function break; } @@ -394,7 +544,7 @@ int source_parse (char *source, unsigned size) return 1; } -char *source_open (char *file) +char *source_open (char *file, unsigned *size) { int fd = open (file, O_RDONLY); @@ -403,19 +553,30 @@ char *source_open (char *file) return 0; } - char *buffer = (char *) malloc (sizeof (char) * 513); + char *buffer = (char *) malloc (sizeof (char) * 10240); if (!buffer) { printf ("ERROR -> out of memory !\n"); return 0; } - if (!read (fd, buffer, 512)) { - printf ("ERROR -> !source_open ()\n"); - return 0; + int ret; + unsigned l = 0; + + while (1) { + ret = read (fd, buffer+l, 512); + + if (ret < 1) + break; + + l += (unsigned) ret; } - printf ("Source: %s\n", buffer); + *size = l; + + close (fd); + + //printf ("Source: %s\n-=-=-=-=-=-=-=-=-\n\n", buffer); return buffer; } diff --git a/apps/zasm/source.h b/apps/zasm/source.h index 93de019..1127b9e 100644 --- a/apps/zasm/source.h +++ b/apps/zasm/source.h @@ -26,13 +26,13 @@ typedef struct var_context { char type; char *name; void *address; - unsigned short line; + unsigned short offset; } var_t; #define VAR_TYPE_GLOBAL 0x1 extern int source_parse (char *source, unsigned size); -extern char *source_open (char *file); +extern char *source_open (char *file, unsigned *size); extern int source_init (); #endif diff --git a/apps/zasm/src b/apps/zasm/src index aeb0e21..5807169 100644 --- a/apps/zasm/src +++ b/apps/zasm/src @@ -1,11 +1,15 @@ ; Example source code for ZeX/OS assembly compiler global entry +global print entry: ; map process mov eax, 46 int 0x80 + ; set ecx register to value 1 + mov ecx, 1 +print: ; print on screen mov eax, 4 mov ebx, 'H' @@ -27,8 +31,19 @@ entry: mov ebx, 10 int 0x80 - ; exit program + ; sleep ([cycle]s) + mov eax, 3 + mov ebx, ecx + int 0x80 + + ; increase ecx register's value + inc ecx + + ; jump to start of print function + jmp print + + ; exit program (this part is not used, because jmp instruction is neverending) mov eax, 1 int 0x80 - ret \ No newline at end of file + ret diff --git a/kernel/.config b/kernel/.config index ed86d1f..5798b2e 100644 --- a/kernel/.config +++ b/kernel/.config @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit # ZeX/OS version: .. -# Mon Oct 20 18:08:04 2008 +# Wed Oct 22 19:14:02 2008 # # diff --git a/kernel/arch/i386/syscall.c b/kernel/arch/i386/syscall.c index 7720b61..3c27df8 100755 --- a/kernel/arch/i386/syscall.c +++ b/kernel/arch/i386/syscall.c @@ -81,9 +81,13 @@ void sys_getch (struct regs *r) *where = c;*/ } +extern unsigned long timer_ticks; void sys_sleep (struct regs *r) { - timer_wait (1000 * (unsigned) r->ebx); + unsigned long timer_start = timer_ticks + ((unsigned) r->ebx * 1000); + + while (timer_start > timer_ticks) + schedule (); } void sys_putch (struct regs *r) -- 2.11.4.GIT