asm

custom asm compiler (learn project)
git clone git://git.evenfri.xyz/asm.git
Log | Files | Refs

commit 1dda79666f828eaa93869257a3560336dc8a4b71
Author: evenfri <evenfri256@gmail.com>
Date:   Sat, 15 Aug 2026 18:44:58 +0800

initial commit

Diffstat:
A.gitignore | 2++
Aasm.h | 14++++++++++++++
Adat.h | 8++++++++
Afns.h | 6++++++
Amain.c | 163+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amkfile | 14++++++++++++++
Atest.asm | 4++++
Autils.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; +} +