zasm assembly compiler support next instruction (jmp; inc; mov 32bit, 32bit; hlt...
[ZeXOS.git] / apps / zasm / source.c
bloba215d0f2a996760cd1bf97e4fae82f8ddbb7087b
1 /*
2 * ZeX/OS
3 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <fcntl.h>
23 #include <ctype.h>
24 #include "buffer.h"
25 #include "source.h"
27 var_t var_list;
28 var_t *function_curr;
29 unsigned bin_pos;
32 var_t *var_find (char *name)
34 var_t *var;
36 for (var = var_list.next; var != &var_list; var = var->next) {
37 if (!strcmp (var->name, name))
38 return var;
41 return 0;
44 int var_create (char type, char *name, unsigned len, void *address, unsigned line)
46 var_t *var;
48 /* alloc and init context */
49 var = (var_t *) malloc (sizeof (var_t));
51 if (!var)
52 return 0;
54 var->type = type;
56 var->name = (char *) malloc (sizeof (char) * (len + 1));
58 if (!var->name)
59 return 0;
61 memcpy (var->name, name, len);
62 var->name[len] = '\0';
64 var->address = address;
65 var->offset = 0;
67 /* add into list */
68 var->next = &var_list;
69 var->prev = var_list.prev;
70 var->prev->next = var;
71 var->next->prev = var;
73 printf ("var_create () -> '%s' on line %d\n", var->name, line);
75 return 1;
78 int source_nextline (char *source, unsigned size)
80 unsigned i;
82 for (i = 0; i < size; i ++) {
83 //printf ("znak: %c : %d\n", source[i], source[i]);
84 if (source[i] == '\n') {
85 //printf ("source_nextline: %d\n", i);
86 return i;
90 return 0;
93 char *source_param (char *source, unsigned *size)
95 unsigned i;
96 char *param = (char *) 0;
97 unsigned len = *size;
99 for (i = 0; i < len; i ++) {
100 if (!param) {
101 if (source[i] == ' ' || source[i] == '\t') {
102 i ++;
103 continue;
106 if ((source[i] >= 'a' && source[i] <= 'z') ||
107 (source[i] >= 'A' && source[i] <= 'Z') ||
108 (source[i] >= '0' && source[i] <= '9'))
109 param = source + i;
110 } else if (source[i] == ' ' || source[i] == '\t' || source[i] == '\n' || source[i] == ';') {
111 *size = i;
112 return param;
116 return 0;
119 char *source_paramfirst (char *source, unsigned *size)
121 unsigned i;
122 char *param = (char *) 0;
123 unsigned len = *size;
125 for (i = 0; i < len; i ++) {
126 if (!param) {
127 if (source[i] == ' ' || source[i] == '\t')
128 continue;
130 if ((source[i] >= 'a' && source[i] <= 'z') ||
131 (source[i] >= 'A' && source[i] <= 'Z') ||
132 (source[i] >= '0' && source[i] <= '9'))
133 param = source + i;
134 } else if (source[i] == ' ' || source[i] == ',' || source[i] == '\t') {
135 *size = i;
136 return param;
140 return 0;
143 char *source_paramsecond (char *source, unsigned *size)
145 unsigned i;
146 char *param = (char *) 0;
147 unsigned len = *size;
149 for (i = 0; i < len; i ++) {
150 if (!param) {
151 if (source[i] == ' ' || source[i] == '\t' || source[i] == ',')
152 continue;
154 if ((source[i] >= 'a' && source[i] <= 'z') ||
155 (source[i] >= 'A' && source[i] <= 'Z') ||
156 (source[i] >= '0' && source[i] <= '9'))
157 param = source + i;
158 else if (source[i] == '\'')
159 param = source + i;
160 } else if (source[i] == ' ' || source[i] == '\t' || source[i] == '\n' || source[i] == ';') {
161 *size = i-2;
162 return param;
166 return 0;
169 int source_parse (char *source, unsigned size)
171 unsigned i;
172 unsigned line = 1;
174 for (i = 0; i < size; i ++) {
175 /* GLOBAL */
176 if (!strncmp ("global ", source+i, 7)) {
177 unsigned var = size-i-7;
178 char *param = source_param (source+i+7, &var);
180 if (!param) {
181 printf ("ERROR -> !param\n");
182 return 0;
185 var_create (VAR_TYPE_GLOBAL, param, var, (void *) 0x0 + i, line);
187 i += source_nextline (source+i, size-i);
189 line ++;
190 continue;
193 /* MOV */
194 if (!strncmp ("mov ", source+i, 4)) {
195 unsigned reg_len = size-i-4;
196 char *paramreg = source_paramfirst (source+i+4, &reg_len);
198 if (!paramreg) {
199 printf ("ERROR -> !paramreg\n");
200 return 0;
203 unsigned val_len = size-reg_len-i-4;
204 char *paramval = source_paramsecond (source+i+reg_len+4, &val_len);
206 if (!paramval) {
207 printf ("ERROR -> !val_len\n");
208 return 0;
211 i += source_nextline (source+i, size-i);
213 paramreg[reg_len] = '\0';
214 paramval[val_len] = '\0';
216 printf ("mov: %s, %s\n", paramreg, paramval);
218 unsigned char reg = 0;
220 if (paramval[0] != 'e') { /* MOV 8bit */
221 if (paramreg[0] == 'e' && paramreg[1] == 'a' && paramreg[2] == 'x')
222 reg = 0xb8; // eax
223 else if (paramreg[0] == 'e' && paramreg[1] == 'b' && paramreg[2] == 'x')
224 reg = 0xbb; // ebx
225 else if (paramreg[0] == 'e' && paramreg[1] == 'c' && paramreg[2] == 'x')
226 reg = 0xb9; // ecx
227 else if (paramreg[0] == 'e' && paramreg[1] == 'd' && paramreg[2] == 'x')
228 reg = 0xba; // edx
230 buffer_copy (bin_pos, (void *) &reg, 1);
231 bin_pos ++;
233 /* Let's convert parameter to binary number */
234 if (paramval[0] == '\'') {
235 if (val_len < 3) {
236 printf ("ERROR -> wrong parameter syntax - %d != 3, line: %d\n", val_len, line);
237 return 0;
240 if (paramval[2] != '\'' || paramval[1] == '\'') {
241 printf ("ERROR -> wrong parameter syntax, line: %d\n", line);
242 return 0;
245 int c = paramval[1];
246 //printf ("mov val char = %c\n", c);
248 buffer_copy (bin_pos, (void *) &c, sizeof (int));
249 bin_pos += sizeof (int);
251 } else if (paramval[0] == '0' && paramval[1] == 'x') {
252 char *endptr, *str = paramval+2;
254 long val = strtol (str, &endptr, 16);
256 //printf ("mov val hexa = %d\n", val);
258 buffer_copy (bin_pos, (void *) &val, sizeof (int));
259 bin_pos += sizeof (int);
260 } else {
261 unsigned x;
262 for (x = 0; x < val_len-1; x ++) {
263 if (!(paramval[x] >= '0' && paramval[x] <= '9')) {
264 printf ("ERROR -> wrong parameter syntax - only numbers are allowed, line: %d\n", line);
265 return 0;
269 int num = atoi (paramval);
271 //printf ("mov val digit = %d\n", num);
273 buffer_copy (bin_pos, (void *) &num, sizeof (int));
274 bin_pos += sizeof (int);
278 } else { /*MOV 32bit */
280 reg = 0x89; // 32bit
282 buffer_copy (bin_pos, (void *) &reg, 1);
283 bin_pos ++;
285 unsigned char regb = 0;
287 if (!strncmp (paramreg, "eax", 3)) {
288 if (!strncmp (paramval, "eax", 3))
289 regb = 0xc0;
290 else if (!strncmp (paramval, "ebx", 3))
291 regb = 0xd8;
292 else if (!strncmp (paramval, "ecx", 3))
293 regb = 0xc8;
294 else if (!strncmp (paramval, "edx", 3))
295 regb = 0xd0;
296 } else if (!strncmp (paramreg, "ebx", 3)) {
297 if (!strncmp (paramval, "eax", 3))
298 regb = 0xc3;
299 else if (!strncmp (paramval, "ebx", 3))
300 regb = 0xdb;
301 else if (!strncmp (paramval, "ecx", 3))
302 regb = 0xcb;
303 else if (!strncmp (paramval, "edx", 3))
304 regb = 0xd3;
305 } else if (!strncmp (paramreg, "ecx", 3)) {
306 if (!strncmp (paramval, "eax", 3))
307 regb = 0xc1;
308 else if (!strncmp (paramval, "ebx", 3))
309 regb = 0xd9;
310 else if (!strncmp (paramval, "ecx", 3))
311 regb = 0xc9;
312 else if (!strncmp (paramval, "edx", 3))
313 regb = 0xd1;
314 } else if (!strncmp (paramreg, "edx", 3)) {
315 if (!strncmp (paramval, "eax", 3))
316 regb = 0xc2;
317 else if (!strncmp (paramval, "ebx", 3))
318 regb = 0xda;
319 else if (!strncmp (paramval, "ecx", 3))
320 regb = 0xca;
321 else if (!strncmp (paramval, "edx", 3))
322 regb = 0xd2;
325 buffer_copy (bin_pos, (void *) &regb, 1);
326 bin_pos ++;
330 line ++;
331 continue;
334 /* INT */
335 if (!strncmp ("int ", source+i, 4)) {
336 unsigned var = size-i-4;
337 char *param = source_param (source+i+4, &var);
339 if (!param) {
340 printf ("ERROR -> !param\n");
341 return 0;
344 i += source_nextline (source+i, size-i);
346 unsigned char intr = 0xcd; // int
347 buffer_copy (bin_pos, (void *) &intr, 1);
348 bin_pos ++;
350 param[var] = '\0';
352 if (param[0] == '0' && param[1] == 'x') {
353 char *endptr, *str = param+2;
355 long val = strtol (str, &endptr, 16);
357 //printf ("int: 0x%x\n", val);
359 buffer_copy (bin_pos, (void *) &val, 1);
360 bin_pos ++;
361 } else {
362 unsigned x;
363 for (x = 0; x < var; x ++) {
364 if (!isdigit (param[x])) {
365 printf ("ERROR -> wrong parameter syntax - only numbers are allowed, line: %d\n", line);
366 return 0;
370 int num = atoi (param);
372 buffer_copy (bin_pos, (void *) &num, 1);
373 bin_pos ++;
376 printf ("int: %s\n", param);
378 line ++;
379 continue;
382 /* JMP */
383 if (!strncmp ("jmp ", source+i, 4)) {
384 unsigned v = size-i-4;
385 char *param = source_param (source+i+4, &v);
387 if (!param) {
388 printf ("ERROR -> !param\n");
389 return 0;
392 i += source_nextline (source+i, size-i);
394 unsigned char jmp = 0xeb; // jmp
395 buffer_copy (bin_pos, (void *) &jmp, 1);
396 bin_pos ++;
398 param[v] = '\0';
400 var_t *var = var_find (param);
402 if (!var) {
403 printf ("ERROR -> unknown variable '%s', line %d\n", source+i, line);
404 return 0;
407 unsigned diff = (bin_pos - var->offset);
409 if (diff > 0xff) {
410 printf ("ERROR -> it is not 'near jump', line %d\n", line);
411 return 0;
414 unsigned char val = 0xff - diff;
416 buffer_copy (bin_pos, (void *) &val, 1);
417 bin_pos ++;
419 printf ("jmp: %s\n", param);
421 line ++;
422 continue;
425 /* INC */
426 if (!strncmp ("inc ", source+i, 4)) {
427 unsigned v = size-i-4;
428 char *param = source_param (source+i+4, &v);
430 if (!param) {
431 printf ("ERROR -> !param\n");
432 return 0;
435 i += source_nextline (source+i, size-i);
437 param[v] = '\0';
439 if (v < 2) {
440 printf ("ERROR -> inc: bad register name '%s', line %d\n", param, line);
441 return 0;
444 unsigned char reg = 0;
446 if (!strncmp (param, "eax", 3))
447 reg = 0x40;
448 else if (!strncmp (param, "ebx", 3))
449 reg = 0x43;
450 else if (!strncmp (param, "ecx", 3))
451 reg = 0x41;
452 else if (!strncmp (param, "edx", 3))
453 reg = 0x42;
455 buffer_copy (bin_pos, (void *) &reg, 1);
456 bin_pos ++;
458 printf ("inc: %s\n", param);
460 line ++;
461 continue;
464 /* RET */
465 if (!strncmp ("ret", source+i, 3)) {
466 if (!function_curr) {
467 printf ("ERROR -> ret cannot be called out of function, line: %d\n", line);
468 return 0;
471 printf ("Function %s end on line %d\n", function_curr->name, line);
473 function_curr = 0;
475 unsigned char ret = 0xc3;
476 buffer_copy (bin_pos, (void *) &ret, 1);
477 bin_pos ++;
479 i += source_nextline (source+i, size-i);
481 line ++;
482 continue;
485 /* HLT */
486 if (!strncmp ("hlt", source+i, 3)) {
487 unsigned char hlt = 0xf4;
488 buffer_copy (bin_pos, (void *) &hlt, 1);
489 bin_pos ++;
491 i += source_nextline (source+i, size-i);
493 line ++;
494 continue;
497 if ((source[i] >= 'a' && source[i] <= 'z') || (source[i] >= 'A' && source[i] <= 'Z')) {
498 unsigned y;
500 for (y = i; y < size-i; y ++) {
501 /* Function */
502 if (source[y] == ':') {
503 source[y] = '\0';
505 var_t *var = var_find (source+i);
507 if (!var) {
508 printf ("ERROR -> unknown variable '%s', line %d\n", source+i, line);
509 return 0;
512 printf ("Function '%s' on line %d\n", var->name, line);
514 var->offset = bin_pos;
516 function_curr = var; // set current function
517 break;
521 if (source[y] == ' ' || source[y] == '\t' || source[y] == '\n' || source[y] == 32 || source[y] == ';') {
522 source[y] = '\0';
524 printf ("ERROR -> unknown command '%s', line: %d - %d, %c\n", source+i, line, i, source[i]);
525 return 0;
529 i = y;
530 } else {
531 //if (source[i] != ' ' || source[i] != ';')
532 //printf ("ERROR -> unspecified character '%c', line: %d\n", source[i], line);
533 if (source[i] == ';') {
534 i += source_nextline (source+i, size-i);
535 line ++;
536 continue;
540 if (source[i] == '\n')
541 line ++;
544 return 1;
547 char *source_open (char *file, unsigned *size)
549 int fd = open (file, O_RDONLY);
551 if (!fd) {
552 printf ("error -> file '%s' not found !\n", file);
553 return 0;
556 char *buffer = (char *) malloc (sizeof (char) * 10240);
558 if (!buffer) {
559 printf ("ERROR -> out of memory !\n");
560 return 0;
563 int ret;
564 unsigned l = 0;
566 while (1) {
567 ret = read (fd, buffer+l, 512);
569 if (ret < 1)
570 break;
572 l += (unsigned) ret;
575 *size = l;
577 close (fd);
579 //printf ("Source: %s\n-=-=-=-=-=-=-=-=-\n\n", buffer);
581 return buffer;
584 int source_init ()
586 var_list.next = &var_list;
587 var_list.prev = &var_list;
589 bin_pos = 0x1000;
591 function_curr = 0;
593 return 1;