aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Chambers <[email protected]>2021-10-02 21:07:42 +1300
committerAndrew Chambers <[email protected]>2021-10-02 21:07:42 +1300
commit58f3466bec7272be9783f6c7be19b5a5299212a0 (patch)
tree79ed5461e4a965725f408f01a7b36fbf6ff8f754
parente12b5b927f5960d0583432e1aa07035295a6b660 (diff)
Assemble two instructions.
-rw-r--r--README.md5
-rw-r--r--asmparser.peg11
-rw-r--r--dumbas.h (renamed from minias.h)20
-rw-r--r--main.c44
4 files changed, 66 insertions, 14 deletions
diff --git a/README.md b/README.md
index 7df1f4b..4eb7c2b 100644
--- a/README.md
+++ b/README.md
@@ -1,13 +1,12 @@
-# minias
+# dumbas
-An assembler for x86_64, written for fun and learning.
+A dumb assembler for x86_64, written for fun and learning.
Goals:
- A simple, tiny, fast implementation (in that order).
- Assemble the output of [cproc](https://github.com/michaelforney/cproc)/[qbe](https://c9x.me/compile/).
- Relocatable elf output.
-- Static linking only.
Non Goals:
diff --git a/asmparser.peg b/asmparser.peg
new file mode 100644
index 0000000..77f90e5
--- /dev/null
+++ b/asmparser.peg
@@ -0,0 +1,11 @@
+%prefix "asmparser"
+
+%value "Parsev"
+
+program <- line* !.
+line <- s:stmt eol { srcpos = $0s; onstmt(s); }
+stmt <- i:instr { $$ = i; }
+instr <- "nop" { $$.instr = (Instr){.kind = ASM_NOP}; }
+ / "ret" { $$.instr = (Instr){.kind = ASM_RET}; }
+ws <- [ \t]*
+eol <- ws ("\n" / ! .)
diff --git a/minias.h b/dumbas.h
index 7ad5883..00f4fad 100644
--- a/minias.h
+++ b/dumbas.h
@@ -5,6 +5,26 @@
#include <stdio.h>
#include <unistd.h>
+typedef struct {
+ Elf64_Shdr hdr;
+ size_t capacity;
+ uint8_t *data;
+} Section;
+
+enum AsmKind {
+ ASM_NOP,
+ ASM_RET
+};
+
+typedef struct {
+ enum AsmKind kind;
+} Instr;
+
+typedef union {
+ enum AsmKind kind;
+ Instr instr;
+} Parsev;
+
static void die(char *s) {
write(STDERR_FILENO, s, strlen(s));
exit(1);
diff --git a/main.c b/main.c
index e0bc8b7..0877d4a 100644
--- a/main.c
+++ b/main.c
@@ -1,15 +1,12 @@
-#include "minias.h"
+#include "dumbas.h"
-typedef struct {
- Elf64_Shdr hdr;
- size_t capacity;
- uint8_t *data;
-} Section;
+int srcpos = 0;
#define MAXSECTIONS 32
static Section sections[MAXSECTIONS];
static size_t nsections = 1; // first is reserved.
+static Section *cursection = NULL;
static Section *shstrtab = NULL;
static Section *strtab = NULL;
static Section *symtab = NULL;
@@ -25,6 +22,10 @@ static void secappend(Section *s, uint8_t *bytes, size_t n) {
s->hdr.sh_size += n;
}
+static void secbyte(Section *s, uint8_t b) {
+ secappend(s, &b, 1);
+}
+
static Elf64_Word elfstr(Section *sec, const char *s) {
Elf64_Word i;
for (i = 0; i < sec->hdr.sh_size; i++) {
@@ -45,16 +46,14 @@ static Section *newsection() {
}
static void initsections(void) {
- uint8_t zb = 0;
-
shstrtab = newsection();
- secappend(shstrtab, &zb, 1);
+ secbyte(shstrtab, 0);
shstrtab->hdr.sh_name = elfstr(shstrtab, ".shstrtab");
shstrtab->hdr.sh_type = SHT_STRTAB;
shstrtab->hdr.sh_entsize = 1;
strtab = newsection();
- secappend(strtab, &zb, 1);
+ secbyte(strtab, 0);
strtab->hdr.sh_name = elfstr(shstrtab, ".strtab");
strtab->hdr.sh_type = SHT_STRTAB;
strtab->hdr.sh_entsize = 1;
@@ -122,8 +121,31 @@ static void outelf(void) {
}
}
-int main() {
+void onstmt(Parsev p) {
+ switch (p.kind) {
+ case ASM_NOP:
+ secbyte(cursection, 0x90);
+ break;
+ case ASM_RET:
+ secbyte(cursection, 0xc3);
+ break;
+ default:
+ die("unexpected kind");
+ }
+}
+
+#include "asmparser.c" // XXX resolve dependency cycle.
+
+void parse(void) {
+ asmparser_context_t *ctx = asmparser_create(NULL);
+ while (asmparser_parse(ctx, NULL));
+ asmparser_destroy(ctx);
+}
+
+int main(void) {
initsections();
+ cursection = text;
+ parse();
outelf();
return 0;
} \ No newline at end of file