commit 1dda79666f828eaa93869257a3560336dc8a4b71
Author: evenfri <evenfri256@gmail.com>
Date: Sat, 15 Aug 2026 18:44:58 +0800
initial commit
Diffstat:
| A | .gitignore | | | 2 | ++ |
| A | asm.h | | | 14 | ++++++++++++++ |
| A | dat.h | | | 8 | ++++++++ |
| A | fns.h | | | 6 | ++++++ |
| A | main.c | | | 163 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | mkfile | | | 14 | ++++++++++++++ |
| A | test.asm | | | 4 | ++++ |
| A | utils.c | | | 46 | ++++++++++++++++++++++++++++++++++++++++++++++ |
8 files changed, 257 insertions(+), 0 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -0,0 +1,2 @@
+*.o
+o.*
diff --git a/asm.h b/asm.h
@@ -0,0 +1,14 @@
+#ifndef asm_h
+#define asm_h
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "dat.h"
+#include "fns.h"
+
+#endif /* asm_h */
diff --git a/dat.h b/dat.h
@@ -0,0 +1,8 @@
+#ifndef dat_h
+#define dat_h
+
+#define PROGRAM_NAME "asm"
+#define CHAR_COMMENT ';'
+#define CHAR_NEWLINE '\n'
+
+#endif /* dat_h */
diff --git a/fns.h b/fns.h
@@ -0,0 +1,6 @@
+#ifndef fns_h
+#define fns_h
+
+char* read_file(char *filename);
+
+#endif /* fns_h */
diff --git a/main.c b/main.c
@@ -0,0 +1,163 @@
+#include "asm.h"
+
+enum token_kind {
+ tok_mnem,
+ tok_dst,
+ tok_src,
+ tok_comma,
+ tok_other,
+};
+
+typedef struct token token;
+struct token {
+ enum token_kind kind;
+ char *val;
+ token *next;
+};
+
+typedef struct {
+ char *name;
+ uint8_t opcode;
+} mnem_t;
+
+static mnem_t mnem_table[] = {
+ {"hlt", 0x00},
+ {"mov", 0x88},
+ {"sub", 0x28},
+};
+static size_t mnem_count = sizeof(mnem_table) / sizeof(mnem_t);
+
+uint8_t mnem_find(char *s) {
+ for (size_t i = 0; i < mnem_count; i++) {
+ if (strcmp(s, mnem_table[i].name) == 0) {
+ return mnem_table[i].opcode;
+ }
+ }
+ fprintf(stderr, "%s: %s: unknown mnemonic\n", PROGRAM_NAME, s);
+ return 0xff;
+}
+
+
+void clear_code(char *s) {
+ char *rd = s;
+ char *wr = s;
+
+ while (*rd != '\0') {
+ if (*rd == CHAR_COMMENT) {
+ while (*rd != '\n' && *rd != '\0') {
+ rd++;
+ }
+ }
+
+ if (*rd == CHAR_NEWLINE) {
+ *wr++ = ' ';
+ rd++;
+ continue;
+ }
+
+ if (*rd != '\0') {
+ *wr++ = *rd++;
+ }
+ }
+ *wr = '\0';
+}
+
+void free_tokens(token *tok) {
+ while (tok) {
+ token *next = tok->next;
+ free(tok->val);
+ free(tok);
+ tok = next;
+ }
+}
+
+token* new_token(enum token_kind kind, char *val) {
+ token *tok = calloc(1, sizeof(token));
+ tok->kind = kind;
+ tok->val = strdup(val);
+
+ return tok;
+}
+
+token* tokenize(char *s) {
+ token head = {0};
+ token *cur = &head;
+
+ char *delim = " \t,";
+ char *p = strtok(s, delim);
+
+ int op_index = 0;
+
+ while (p != NULL) {
+ enum token_kind kind;
+
+ int is_mnemonic = 0;
+ for (size_t i = 0; i < mnem_count; i++) {
+ if (strcmp(p, mnem_table[i].name) == 0) {
+ is_mnemonic = 1;
+ break;
+ }
+ }
+
+ if (is_mnemonic) {
+ op_index = 0;
+ }
+
+ if (op_index == 0) {
+ kind = tok_mnem;
+ } else if (op_index == 1) {
+ kind = tok_dst;
+ } else {
+ kind = tok_src;
+ }
+ op_index++;
+
+ cur->next = new_token(kind, p);
+ cur = cur->next;
+
+ p = strtok(NULL, delim);
+ }
+ return head.next;
+}
+
+int main(int argc, char *argv[]) {
+ if (argc < 2) {
+ fprintf(stderr, "%s: no input files\n", PROGRAM_NAME);
+ exit(1);
+ }
+
+ char *code = read_file(argv[1]);
+ if (!code) {
+ perror(PROGRAM_NAME);
+ exit(1);
+ }
+
+ clear_code(code);
+
+ token *head = tokenize(code);
+ token *curr = head;
+
+ while (curr != NULL) {
+ printf("%s is ", curr->val);
+
+ if (curr->kind == tok_mnem) {
+ uint8_t opcode = mnem_find(curr->val);
+ printf("0x%02x", opcode);
+ }
+
+ if (curr->kind == tok_dst) {
+ printf("dest");
+ }
+
+ if (curr->kind == tok_src) {
+ printf("src");
+ }
+
+ printf("\n");
+ curr = curr->next;
+ }
+
+ free_tokens(head);
+ free(code);
+ return 0;
+}
diff --git a/mkfile b/mkfile
@@ -0,0 +1,14 @@
+<$PLAN9/src/mkhdr
+
+ld = gcc
+
+ofiles = main.$o \
+ utils.$o \
+
+hfiles = asm.h \
+ fns.h \
+ dat.h
+
+targ = asm
+
+<$PLAN9/src/mkone
diff --git a/test.asm b/test.asm
@@ -0,0 +1,4 @@
+mov bx, 2 ; comment
+mov ax, bx ; new comment
+sub ax, 2 ; comment 5
+hlt
diff --git a/utils.c b/utils.c
@@ -0,0 +1,46 @@
+#include "asm.h"
+
+char* read_file(char *filename) {
+ int fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ perror(PROGRAM_NAME);
+ exit(1);
+ }
+
+ off_t size = lseek(fd, 0, SEEK_END);
+ if (size == -1) {
+ close(fd);
+ return NULL;
+ }
+ lseek(fd, 0, SEEK_SET);
+
+ char *buf = malloc(size + 1);
+ if (!buf) {
+ close(fd);
+
+ perror(PROGRAM_NAME);
+ exit(1);
+ }
+
+ ssize_t total_read = 0;
+ ssize_t bytes_read;
+ while (total_read < size) {
+ bytes_read = read(fd, buf + total_read, size - total_read);
+ if (bytes_read == -1) {
+ free(buf);
+ close(fd);
+
+ perror(PROGRAM_NAME);
+ exit(1);
+ }
+ if (bytes_read == 0) {
+ break;
+ }
+ total_read += bytes_read;
+ }
+
+ buf[size] = '\0';
+ close(fd);
+ return buf;
+}
+