ref: f7ecd7063b03eb0604490bb2e3d335cbf3873813
parent: c1a3310fbbad48582811bb35438f194bbab27c3e
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Mon Sep 11 04:15:21 EDT 2017
[as] Add symbol definition A symbol is only defined putting it at the beginning of a line and it takes the value of the current pc in the current segment. At the same the statement EQU can be used and set an absolute value in the symbol.
--- a/as/as.h
+++ b/as/as.h
@@ -1,16 +1,27 @@
+/*
+ * First 3 bits of flags in segments and symbols are for the
+ * type of segment
+ */
+enum symtype {
+ TABS = 1,
+ TTEXT = 2,
+ TBSS = 3,
+ TDATA = 4,
+ TMASK = 7,
+};
+
enum secflags {
- SRELOC,
- SREAD,
- SWRITE,
- SFILE,
+ SRELOC = 1 << 4,
+ SREAD = 1 << 5,
+ SWRITE = 1 << 6,
+ SFILE = 1 << 7,
};
enum symflags {
- FUNDEF = 'U',
- FABS = 'A',
- FCOMMON = 'C',
- FBSS = 'B',
- FDATA = 'D',
+ FCOMMON = 1 << 4,
+ FLOCAL = 1 << 5,
+ FEXTERN = 1 << 6,
+ FUNDEF = 1 << 7,
};
enum args {
@@ -24,6 +35,8 @@
LITTLE_ENDIAN = 1
};
+#define MAXSYM 63
+
typedef struct ins Ins;
typedef struct op Op;
typedef struct arg Arg;
@@ -58,7 +71,7 @@
struct section {
char *name;
char *mem;
- int flags;
+ unsigned char flags;
TUINT base;
TUINT max;
TUINT curpc;
@@ -68,7 +81,8 @@
struct symbol {
char *name;
- char type;
+ unsigned char flags;
+ char pass;
short desc;
TUINT value;
struct symbol *next;
@@ -83,6 +97,7 @@
extern void error(char *msg, ...);
extern Arg *getargs(char *s);
extern Symbol *lookup(char *name);
+extern Symbol *deflabel(char *name);
/* Avoid errors in files where stdio is not included */
#ifdef stdin
--- a/as/emit.c
+++ b/as/emit.c
@@ -9,26 +9,26 @@
#define HASHSIZ 64
static Section abss = {
- .name = "abs",
- .flags = SREAD|SWRITE
+ .name = "abs",
+ .flags = TABS|SREAD|SWRITE,
};
static Section bss = {
- .name = "bss",
- .flags = SRELOC|SREAD|SWRITE,
- .next = &abss
+ .name = "bss",
+ .flags = TBSS|SRELOC|SREAD|SWRITE,
+ .next = &abss,
};
static Section data = {
- .name = "data",
- .next = &bss,
- .flags = SRELOC|SREAD|SWRITE|SFILE
+ .name = "data",
+ .flags = TDATA|SRELOC|SREAD|SWRITE|SFILE,
+ .next = &bss,
};
static Section text = {
- .name = "text",
- .next = &data,
- .flags = SRELOC|SFILE
+ .name = "text",
+ .flags = TTEXT|SRELOC|SFILE,
+ .next = &data,
};
Section *cursec = &text, *headp = &text;
@@ -36,6 +36,7 @@
int pass;
static Symbol *hashtbl[HASHSIZ];
+Symbol *linesym;
Symbol *
lookup(char *name)
@@ -60,12 +61,48 @@
sym = xmalloc(sizeof(*sym));
sym->name = xstrdup(name);
- sym->type = FUNDEF;
+ sym->flags = (cursec->flags & TMASK) | FLOCAL | FUNDEF;
sym->desc = 0;
sym->value = 0;
sym->next = *list;
*list = sym;
+ return sym;
+}
+
+Symbol *
+deflabel(char *name)
+{
+ static Symbol *cursym;
+ Symbol *sym;
+ char label[MAXSYM+1];
+
+ if (*name == '.') {
+ int r;
+
+ if (!cursym) {
+ error("local label '%s' without global label", name);
+ return NULL;
+ }
+ r = snprintf(label, sizeof(label),
+ "%s%s",
+ cursym->name, name);
+ if (r == sizeof(label)) {
+ error("local label '%s' in '%s' produces too long symbol",
+ name, cursym->name);
+ return NULL;
+ }
+ name = label;
+ }
+
+ sym = lookup(name);
+ if (pass == 1 && (sym->flags & FUNDEF) == 0)
+ error("redefinition of label '%s'", name);
+ sym->flags &= ~FUNDEF;
+ sym->value = cursec->curpc;
+
+ if (*name != '.')
+ cursym = sym;
return sym;
}
--- a/as/ins.c
+++ b/as/ins.c
@@ -38,3 +38,12 @@
{
def(args, 8);
}
+
+void
+equ(Op *op, Arg *args)
+{
+ if (!linesym)
+ error("label definition lacks a label");
+ else
+ linesym->value = args->val;
+}
--- a/as/main.c
+++ b/as/main.c
@@ -82,8 +82,17 @@
die("as: error opening '%s'", fname);
isections();
- while (next(fp, &line))
- as(line.op, line.args);
+ while (next(fp, &line)) {
+ linesym = NULL;
+
+ if (line.label)
+ linesym = deflabel(line.label);
+
+ if (line.op)
+ as(line.op, line.args);
+ else if (line.args)
+ error("arguments without an opcode");
+ }
if (fclose(fp))
die("as: error reading from input file '%s'", fname);
--- a/as/target/x86/i386.dat
+++ b/as/target/x86/i386.dat
@@ -1,4 +1,5 @@
# Tab 16, tabs 16, :set ts=16
# op args size bytes format
+EQU imm32 0 none equ
NOP none 1 0x90 direct
RET none 1 0xc3 direct