Compare commits

...

2 Commits

Author SHA1 Message Date
0bdbaa7f1f extract assembling line 2025-04-01 17:15:37 +02:00
af0214739c parse done 2025-04-01 15:47:25 +02:00
9 changed files with 740 additions and 620 deletions

View File

@ -8,7 +8,6 @@ C_FLAGS = \
-Wall -Wextra -Wpedantic -Wconversion \
-pedantic -pedantic-errors \
-Wno-unused-variable \
-Wno-unused-parameter \
-I. \
L_FLAGS = -pthread

308
asm/asm.c
View File

@ -17,62 +17,26 @@ static inline void set_mov_addr_is_reg(uint32_t* ins);
static inline void set_mov_is_store(uint32_t* ins);
static inline uint16_t linety_arithm_ins(LineTy ty);
uint16_t assemble_to_binary(uint16_t* out, const Line* lines, size_t lines_size)
uint16_t assemble_line(uint16_t* out, const Line* line)
{
const bool debug = false;
uint16_t ip = 0;
typedef struct {
int label;
uint16_t ptr;
} UnresolvedLabel;
typedef struct {
int label;
uint16_t ip;
} ResolvedLabel;
UnresolvedLabel* unres_labels = malloc(sizeof(UnresolvedLabel) * 64);
size_t unres_labels_size = 0;
ResolvedLabel* res_labels = malloc(sizeof(ResolvedLabel) * 64);
size_t res_labels_size = 0;
#define ADD_LABEL(LABEL) \
{ \
unres_labels[unres_labels_size++] = (UnresolvedLabel) { LABEL, ip }; \
out[ip++] = 0; \
}
if (debug) {
printf("assembling...\n");
printf("ip op n data...\n");
}
for (size_t i = 0; i < lines_size; ++i) {
bool is_label = false;
bool is_data = false;
const Line* line = &lines[i];
uint16_t ins_ip = ip;
switch (line->ty) {
case LineTy_Label: {
res_labels[res_labels_size++]
= (ResolvedLabel) { line->op1.label, ip * 2 };
is_label = true;
case LineTy_Label:
case LineTy_DataLabel:
case LineTy_Jmp_Label:
case LineTy_Jnz_Label:
case LineTy_Cmp_Label:
case LineTy_Mov16_Reg_Label:
case LineTy_Mov16_Reg_MemLabel:
case LineTy_Mov16_MemLabel_Reg:
case LineTy_Call_Label:
case LineTy_Lit_Label: {
fprintf(stderr, "error: labels not supported %d\n", line->ty);
break;
}
case LineTy_DataImm: {
out[ip++] = line->op1.imm;
is_data = true;
break;
}
case LineTy_DataLabel: {
ADD_LABEL(line->op1.label);
is_data = true;
break;
}
case LineTy_Nop: {
@ -100,15 +64,6 @@ uint16_t assemble_to_binary(uint16_t* out, const Line* lines, size_t lines_size)
out[ip++] = op1;
break;
}
case LineTy_Jmp_Label: {
int op1 = line->op1.label;
uint32_t ins = Op_Jmp;
set_is_imm(&ins);
out[ip++] = (uint16_t)ins;
ADD_LABEL(op1);
break;
}
case LineTy_JmpFar_Reg_Reg: {
uint16_t op1 = line->op1.reg;
uint16_t op2 = line->op2.reg;
@ -184,18 +139,6 @@ uint16_t assemble_to_binary(uint16_t* out, const Line* lines, size_t lines_size)
out[ip++] = op2;
break;
}
case LineTy_Jnz_Label: {
uint16_t op1 = line->op1.reg;
int op2 = line->op2.label;
uint32_t ins = Op_Jnz;
set_is_imm(&ins);
add_op1_reg(&ins, op1);
out[ip++] = (uint16_t)ins;
ADD_LABEL(op2);
break;
}
case LineTy_Cmp_Reg: {
uint16_t op1 = line->op1.reg;
uint16_t op2 = line->op2.reg;
@ -219,18 +162,6 @@ uint16_t assemble_to_binary(uint16_t* out, const Line* lines, size_t lines_size)
out[ip++] = op2;
break;
}
case LineTy_Cmp_Label: {
uint16_t op1 = line->op1.reg;
int op2 = line->op2.label;
uint32_t ins = Op_Cmp;
set_is_imm(&ins);
add_op1_reg(&ins, op1);
out[ip++] = (uint16_t)ins;
ADD_LABEL(op2);
break;
}
case LineTy_Mov8_Reg_Reg: {
uint16_t dst = line->dst.reg;
uint16_t op2 = line->op2.reg;
@ -362,18 +293,6 @@ uint16_t assemble_to_binary(uint16_t* out, const Line* lines, size_t lines_size)
out[ip++] = op2;
break;
}
case LineTy_Mov16_Reg_Label: {
uint16_t dst = line->dst.reg;
int op2 = line->op2.label;
uint32_t ins = Op_Mov16;
set_is_imm(&ins);
ins |= (dst & 0xfu) << 12;
out[ip++] = (uint16_t)ins;
ADD_LABEL(op2);
break;
}
case LineTy_Mov16_Reg_MemReg: {
uint16_t dst = line->dst.reg;
uint16_t op2 = line->op2.reg;
@ -401,18 +320,6 @@ uint16_t assemble_to_binary(uint16_t* out, const Line* lines, size_t lines_size)
out[ip++] = op2;
break;
}
case LineTy_Mov16_Reg_MemLabel: {
uint16_t dst = line->dst.reg;
uint32_t ins = Op_Mov16;
set_is_imm(&ins);
set_mov_is_memory(&ins);
add_dst_reg(&ins, dst);
out[ip++] = (uint16_t)ins;
ADD_LABEL(line->op2.label);
break;
}
case LineTy_Mov16_MemReg_Reg: {
uint16_t dst = line->dst.reg;
uint16_t op2 = line->op2.reg;
@ -471,19 +378,6 @@ uint16_t assemble_to_binary(uint16_t* out, const Line* lines, size_t lines_size)
out[ip++] = op2;
break;
}
case LineTy_Mov16_MemLabel_Reg: {
int dst = line->dst.label;
uint16_t op2 = line->op2.reg;
uint32_t ins = Op_Mov16;
add_op2_reg(&ins, op2);
set_mov_is_memory(&ins);
set_mov_is_store(&ins);
out[ip++] = (uint16_t)ins;
ADD_LABEL(dst);
break;
}
case LineTy_In_Reg: {
uint16_t dst = line->dst.reg;
uint16_t op1 = line->op1.reg;
@ -526,16 +420,6 @@ uint16_t assemble_to_binary(uint16_t* out, const Line* lines, size_t lines_size)
out[ip++] = op1;
break;
}
case LineTy_Call_Label: {
int op1 = line->op1.label;
uint32_t ins = Op_Call;
set_is_imm(&ins);
out[ip++] = (uint16_t)ins;
ADD_LABEL(op1);
break;
}
case LineTy_CallFar_Reg_Reg: {
uint16_t op1 = line->op1.reg;
uint16_t op2 = line->op2.reg;
@ -618,16 +502,6 @@ uint16_t assemble_to_binary(uint16_t* out, const Line* lines, size_t lines_size)
out[ip++] = op1;
break;
}
case LineTy_Lit_Label: {
int op1 = line->op1.label;
uint32_t ins = Op_Lit;
set_is_imm(&ins);
out[ip++] = (uint16_t)ins;
ADD_LABEL(op1);
break;
}
case LineTy_Int: {
uint16_t int_id = line->op1.imm & 0xff;
@ -704,6 +578,164 @@ uint16_t assemble_to_binary(uint16_t* out, const Line* lines, size_t lines_size)
break;
}
}
return ip;
}
uint16_t assemble_lines_with_labels(
uint16_t* out, const Line* lines, size_t lines_size)
{
const bool debug = false;
uint16_t ip = 0;
typedef struct {
int label;
uint16_t ptr;
} UnresolvedLabel;
typedef struct {
int label;
uint16_t ip;
} ResolvedLabel;
UnresolvedLabel* unres_labels = malloc(sizeof(UnresolvedLabel) * 64);
size_t unres_labels_size = 0;
ResolvedLabel* res_labels = malloc(sizeof(ResolvedLabel) * 64);
size_t res_labels_size = 0;
#define ADD_LABEL(LABEL) \
{ \
unres_labels[unres_labels_size++] = (UnresolvedLabel) { LABEL, ip }; \
out[ip++] = 0; \
}
if (debug) {
printf("assembling...\n");
printf("ip op n data...\n");
}
for (size_t i = 0; i < lines_size; ++i) {
bool is_label = false;
bool is_data = false;
const Line* line = &lines[i];
uint16_t ins_ip = ip;
switch (line->ty) {
case LineTy_Label: {
res_labels[res_labels_size++]
= (ResolvedLabel) { line->op1.label, ip * 2 };
is_label = true;
break;
}
case LineTy_DataImm: {
ip += assemble_line(&out[ip], line);
is_data = true;
break;
}
case LineTy_DataLabel: {
ADD_LABEL(line->op1.label);
is_data = true;
break;
}
case LineTy_Jmp_Label: {
int op1 = line->op1.label;
uint32_t ins = Op_Jmp;
set_is_imm(&ins);
out[ip++] = (uint16_t)ins;
ADD_LABEL(op1);
break;
}
case LineTy_Jnz_Label: {
uint16_t op1 = line->op1.reg;
int op2 = line->op2.label;
uint32_t ins = Op_Jnz;
set_is_imm(&ins);
add_op1_reg(&ins, op1);
out[ip++] = (uint16_t)ins;
ADD_LABEL(op2);
break;
}
case LineTy_Cmp_Label: {
uint16_t op1 = line->op1.reg;
int op2 = line->op2.label;
uint32_t ins = Op_Cmp;
set_is_imm(&ins);
add_op1_reg(&ins, op1);
out[ip++] = (uint16_t)ins;
ADD_LABEL(op2);
break;
}
case LineTy_Mov16_Reg_Label: {
uint16_t dst = line->dst.reg;
int op2 = line->op2.label;
uint32_t ins = Op_Mov16;
set_is_imm(&ins);
ins |= (dst & 0xfu) << 12;
out[ip++] = (uint16_t)ins;
ADD_LABEL(op2);
break;
}
case LineTy_Mov16_Reg_MemLabel: {
uint16_t dst = line->dst.reg;
uint32_t ins = Op_Mov16;
set_is_imm(&ins);
set_mov_is_memory(&ins);
add_dst_reg(&ins, dst);
out[ip++] = (uint16_t)ins;
ADD_LABEL(line->op2.label);
break;
}
case LineTy_Mov16_MemLabel_Reg: {
int dst = line->dst.label;
uint16_t op2 = line->op2.reg;
uint32_t ins = Op_Mov16;
add_op2_reg(&ins, op2);
set_mov_is_memory(&ins);
set_mov_is_store(&ins);
out[ip++] = (uint16_t)ins;
ADD_LABEL(dst);
break;
}
case LineTy_Call_Label: {
int op1 = line->op1.label;
uint32_t ins = Op_Call;
set_is_imm(&ins);
out[ip++] = (uint16_t)ins;
ADD_LABEL(op1);
break;
}
case LineTy_Lit_Label: {
int op1 = line->op1.label;
uint32_t ins = Op_Lit;
set_is_imm(&ins);
out[ip++] = (uint16_t)ins;
ADD_LABEL(op1);
break;
}
default: {
ip += assemble_line(&out[ip], line);
break;
}
}
if (debug) {
if (!is_label) {

View File

@ -114,7 +114,7 @@ typedef struct {
uint16_t offset;
} Line;
uint16_t assemble_to_binary(
uint16_t assemble_lines_with_labels(
uint16_t* out, const Line* lines, size_t lines_size);
Line s_label(int label);

View File

@ -105,6 +105,7 @@ Line s_jnz_l(Reg op1_reg, int op2_label)
{
return (Line) {
.ty = LineTy_Jnz_Label,
.op1 = (Ex) { .reg = (uint16_t)op1_reg },
.op2 = (Ex) { .label = op2_label },
};
}

View File

@ -37,6 +37,8 @@ typedef enum {
TT_Int,
TT_Binary,
TT_Hex,
TT_Char,
TT_Str,
TT_Newline = '\n',
TT_DoubleLt,
TT_DoubleGt,
@ -119,6 +121,18 @@ static inline Tok lexer_tok(const Lexer* lexer, TokTy ty, Loc loc)
return (Tok) { .ty = ty, .loc = loc, .len = lexer->idx - loc.idx };
}
static inline int lexer_skip_literal_char(Lexer* lexer)
{
char ch = lexer->ch;
lexer_step(lexer);
if (ch == '\\') {
if (lexer_done(lexer))
return -1;
lexer_step(lexer);
}
return 0;
}
static inline void lexer_report(Lexer* lexer, const char* msg, Loc loc)
{
lexer->error_occured = true;
@ -146,14 +160,14 @@ static inline void lexer_report(Lexer* lexer, const char* msg, Loc loc)
loc.line,
line_len,
line,
loc.col - 2,
loc.col - 1,
' ');
}
Tok lexer_next(Lexer* lexer)
{
const char* ident_chars = "abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ_";
"ABCDEFGHIJKLMNOPQRSTUVWXYZ_$";
const char* int_chars = "1234567890";
const char* hex_chars = "01234567889abcdefABCDEF";
@ -212,6 +226,26 @@ Tok lexer_next(Lexer* lexer)
} else {
return lexer_tok(lexer, TT_Int, loc);
}
} else if (lexer->ch == '\'') {
lexer_step(lexer);
lexer_skip_literal_char(lexer);
if (lexer_done(lexer) || lexer->ch != '\'') {
lexer_report(lexer, "malformed character literal", loc);
return lexer_tok(lexer, TT_Err, loc);
}
lexer_step(lexer);
return lexer_tok(lexer, TT_Char, loc);
} else if (lexer->ch == '"') {
lexer_step(lexer);
while (!lexer_done(lexer) && lexer->ch != '"') {
lexer_skip_literal_char(lexer);
}
if (lexer_done(lexer) || lexer->ch != '"') {
lexer_report(lexer, "malformed string literal", loc);
return lexer_tok(lexer, TT_Err, loc);
}
lexer_step(lexer);
return lexer_tok(lexer, TT_Str, loc);
} else if (lexer->ch == '<') {
lexer_step(lexer);
if (!lexer_done(lexer) && lexer->ch == '<') {
@ -235,9 +269,9 @@ Tok lexer_next(Lexer* lexer)
lexer_step(lexer);
return lexer_tok(lexer, (TokTy)ch, loc);
} else {
lexer_report(lexer, "illegal character '%c'", loc);
lexer_report(lexer, "illegal character", loc);
lexer_step(lexer);
return lexer_next(lexer);
return lexer_tok(lexer, TT_Err, loc);
}
}
@ -293,6 +327,7 @@ typedef enum {
PoTy_Imm,
PoTy_Ident,
PoTy_SubLabel,
PoTy_Str,
PoTy_MemU8,
PoTy_MemU16,
PoTy_Not,
@ -317,7 +352,7 @@ struct POperand {
union {
Reg reg;
uint16_t imm;
char* ident;
char* str;
POperand* operand;
struct {
POperand* left;
@ -338,10 +373,10 @@ POperand* poperand_new_imm(uint16_t imm, Loc loc)
*operand = (POperand) { .ty = PoTy_Imm, .loc = loc, .imm = imm };
return operand;
}
POperand* poperand_new_ident(POperandTy ty, char* ident, Loc loc)
POperand* poperand_new_str(POperandTy ty, char* str, Loc loc)
{
POperand* operand = malloc(sizeof(POperand));
*operand = (POperand) { .ty = ty, .loc = loc, .ident = ident };
*operand = (POperand) { .ty = ty, .loc = loc, .str = str };
return operand;
}
POperand* poperand_new_unary(POperandTy ty, POperand* inner, Loc loc)
@ -366,7 +401,8 @@ void poperand_free(POperand* operand)
break;
case PoTy_Ident:
case PoTy_SubLabel:
free(operand->ident);
case PoTy_Str:
free(operand->str);
break;
case PoTy_MemU8:
case PoTy_MemU16:
@ -399,40 +435,19 @@ typedef struct {
POperand* ops[];
} PLine;
PLine* pline_new_0(char* op, PLabel* labels, Loc loc)
PLine* pline_new(
char* op, PLabel* labels, Loc loc, size_t ops_size, POperand** ops)
{
PLine* line = malloc(sizeof(PLine) + sizeof(POperand*) * 0);
*line = (PLine) { .labels = labels, .op = op, .loc = loc, .ops_size = 0 };
return line;
PLine* line = malloc(sizeof(PLine) + sizeof(POperand*) * ops_size);
*line = (PLine) {
.labels = labels,
.op = op,
.loc = loc,
.ops_size = ops_size,
};
for (size_t i = 0; i < ops_size; ++i) {
line->ops[i] = ops[i];
}
PLine* pline_new_1(char* op, PLabel* labels, Loc loc, POperand* op0)
{
PLine* line = malloc(sizeof(PLine) + sizeof(POperand*) * 1);
*line = (PLine) { .labels = labels, .op = op, .loc = loc, .ops_size = 1 };
line->ops[0] = op0;
return line;
}
PLine* pline_new_2(
char* op, PLabel* labels, Loc loc, POperand* op0, POperand* op1)
{
PLine* line = malloc(sizeof(PLine) + sizeof(POperand*) * 2);
*line = (PLine) { .labels = labels, .op = op, .loc = loc, .ops_size = 2 };
line->ops[0] = op0;
line->ops[1] = op1;
return line;
}
PLine* pline_new_3(char* op,
PLabel* labels,
Loc loc,
POperand* op0,
POperand* op1,
POperand* op2)
{
PLine* line = malloc(sizeof(PLine) + sizeof(POperand*) * 3);
*line = (PLine) { .labels = labels, .op = op, .loc = loc, .ops_size = 3 };
line->ops[0] = op0;
line->ops[1] = op1;
line->ops[2] = op2;
return line;
}
void pline_free(PLine* pline)
@ -523,7 +538,7 @@ static inline void parser_report(Parser* parser, const char* msg, Loc loc)
loc.line,
line_len,
line,
loc.col - 2,
loc.col - 1,
' ');
}
@ -572,6 +587,24 @@ static inline PLabel* parser_parse_labels(
return labels;
}
static inline char literal_char_val(const char* str)
{
if (str[0] == '\\') {
switch (str[1]) {
case '0':
return 0;
case 't':
return '\t';
case 'n':
return '\n';
default:
return str[1];
}
} else {
return str[0];
}
}
static const int parser_binary_prec = 6;
static inline POperand* parser_parse_operand_2(Parser* parser, int prec);
@ -590,7 +623,7 @@ static inline POperand* parser_parse_operand_0(Parser* parser)
return poperand_new_reg(reg_val[i], loc);
}
}
return poperand_new_ident(PoTy_Ident, ident, loc);
return poperand_new_str(PoTy_Ident, ident, loc);
} else if (parser_eat(parser, TT_Int)) {
char* str = parser_ident_val(parser, parser->eaten);
uint16_t imm = (uint16_t)strtoul(str, NULL, 10);
@ -606,13 +639,28 @@ static inline POperand* parser_parse_operand_0(Parser* parser)
uint16_t imm = (uint16_t)strtoul(&str[2], NULL, 16);
free(str);
return poperand_new_imm(imm, loc);
} else if (parser_eat(parser, TT_Char)) {
char* str = parser_ident_val(parser, parser->eaten);
uint16_t imm = (uint16_t)literal_char_val(&str[1]);
free(str);
return poperand_new_imm(imm, loc);
} else if (parser_eat(parser, TT_Str)) {
char* lit = parser_ident_val(parser, parser->eaten);
size_t lit_len = strlen(lit);
char* str = calloc(lit_len - 1, sizeof(char));
size_t str_len = 0;
for (size_t i = 1; i < lit_len - 2; ++i) {
str[i] = literal_char_val(&lit[i]);
}
free(lit);
return poperand_new_str(PoTy_Str, str, loc);
} else if (parser_eat(parser, '.')) {
if (!parser_eat(parser, TT_Ident)) {
parser_report(parser, "expected identifier", parser->tok.loc);
return NULL;
}
char* ident = parser_ident_val(parser, parser->eaten);
return poperand_new_ident(PoTy_SubLabel, ident, loc);
return poperand_new_str(PoTy_SubLabel, ident, loc);
} else if (parser_eat(parser, '(')) {
POperand* operand = parser_parse_operand_2(parser, parser_binary_prec);
if (!parser_eat(parser, ')')) {
@ -697,13 +745,18 @@ static inline POperand* parser_parse_operand_2(Parser* parser, int prec)
static inline POperand* parser_parse_operand_3(Parser* parser)
{
Loc loc = parser->tok.loc;
if (parser_eat(parser, TT_LBracket)) {
parser_report(parser, "expected 'u8' or 'u16'", loc);
return NULL;
}
if (!parser_test(parser, TT_Ident)) {
return parser_parse_operand_2(parser, parser_binary_prec);
}
Loc loc = parser->tok.loc;
char* ident = parser_ident_val(parser, parser->eaten);
char* ident = parser_ident_val(parser, parser->tok);
if (strcmp(ident, "u8") == 0) {
free(ident);
parser_step(parser);
if (!parser_eat(parser, '[')) {
parser_report(parser, "expected '['", parser->tok.loc);
return NULL;
@ -717,6 +770,7 @@ static inline POperand* parser_parse_operand_3(Parser* parser)
return poperand_new_unary(PoTy_MemU8, operand, loc);
} else if (strcmp(ident, "u16") == 0) {
free(ident);
parser_step(parser);
if (!parser_eat(parser, '[')) {
parser_report(parser, "expected '['", parser->tok.loc);
return NULL;
@ -740,7 +794,9 @@ PLine* parser_next(Parser* parser)
Loc loc;
PLabel* labels = parser_parse_labels(parser, &ident, &loc);
POperand* ops[3];
const size_t max_ops_size = 64;
// TODO: Move allocation out-of-band.
POperand** ops = malloc(sizeof(POperand) * max_ops_size);
size_t ops_size = 0;
if (!parser_test(parser, TT_Eof) && !parser_test(parser, '\n')) {
@ -751,6 +807,12 @@ PLine* parser_next(Parser* parser)
ops[ops_size++] = operand;
while (!parser_test(parser, TT_Eof) && !parser_test(parser, '\n')
&& ops_size < 3) {
if (ops_size >= max_ops_size) {
parser_report(parser,
"exceeded maximum number of operands (64)",
parser->tok.loc);
goto error_free_ops;
}
if (!parser_eat(parser, ',')) {
parser_report(parser, "expected ','", parser->tok.loc);
goto error_free_ops;
@ -768,22 +830,15 @@ PLine* parser_next(Parser* parser)
}
parser_skip_newlines(parser);
switch (ops_size) {
case 0:
return pline_new_0(ident, labels, loc);
case 1:
return pline_new_1(ident, labels, loc, ops[0]);
case 2:
return pline_new_2(ident, labels, loc, ops[0], ops[1]);
case 3:
default:
return pline_new_3(ident, labels, loc, ops[0], ops[1], ops[2]);
}
PLine* line = pline_new(ident, labels, loc, ops_size, ops);
free(ops);
return line;
error_free_ops:
for (size_t i = 0; i < ops_size; ++i)
if (ops[i])
poperand_free(ops[i]);
free(ops);
plabel_free(labels);
free(ident);
return NULL;

View File

@ -7,7 +7,7 @@
-pedantic
-pedantic-errors
-Wno-unused-variable
-Wno-unused-parameter
# -Wno-unused-parameter
# -Wno-unused-function
-I.

View File

@ -1,7 +1,7 @@
start:
; rsp points *at* the top element
mov Rbp, 2048
mov rbp, 2048
mov rsp, 2048 - 2
lit interrupt_table
@ -25,12 +25,22 @@ interrupt_table:
keyboard_interrupt:
and rfl, rfl, !(1 << Fl_Int)
push rbp
; push rbp
add rsp, rsp, 2
mov u16 [rsp], rbp
mov rbp, Rsp
push r0
push r1
push r2
push r3
; push r0
add rsp, rsp, 2
mov u16 [rsp], r0
; push r1
add rsp, rsp, 2
mov u16 [rsp], r1
; push r2
add rsp, rsp, 2
mov u16 [rsp], r2
; push r3
add rsp, rsp, 2
mov u16 [rsp], r3
in r0, Device_Keyboard
@ -52,7 +62,7 @@ keyboard_interrupt:
jmp .L3
.L0:
mov R0, 32 ; ' '
mov R0, ' '
call put_char
jmp .L4
@ -80,26 +90,42 @@ keyboard_interrupt:
jmp .L4
.L3:
; add r0, r0, 'A' - 4
add r0, r0, 'A' - 4
call put_char
jmp .L4
.L4:
pop r3
pop r2
pop r1
pop r0
; pop r3
mov r3, u16 [rsp]
sub rsp, rsp, 2
; pop r2
mov r2, u16 [rsp]
sub rsp, rsp, 2
; pop r1
mov r1, u16 [rsp]
sub rsp, rsp, 2
; pop r0
mov r0, u16 [rsp]
sub rsp, rsp, 2
mov rsp, rbp
pop rbp
; pop rbp
mov rbp, u16 [rsp]
sub rsp, rsp, 2
or rfl, rfl, 1 << Fl_Int
iret
put_char:
push rbp
; push rbp
add rsp, rsp, 2
mov u16 [rsp], rbp
mov rbp, rsp
push r1
push r2
; push r1
add rsp, rsp, 2
mov u16 [rsp], r1
; push r2
add rsp, rsp, 2
mov u16 [rsp], r2
mov r2, screen_y
mul r2, r2, vcd_width_in_ch
@ -126,10 +152,16 @@ put_char:
mov screen_x, r1
.L1:
pop r1
pop r2
; pop r1
mov r1, u16 [rsp]
sub rsp, rsp, 2
; pop r2
mov r2, u16 [rsp]
sub rsp, rsp, 2
mov rsp, rbp
pop rbp
; pop rbp
mov rbp, u16 [rsp]
sub rsp, rsp, 2
ret
screen_x:

View File

@ -203,7 +203,7 @@ void write_program(FILE* fp)
printf("assembling program...\n");
uint16_t program_size
= assemble_to_binary(program, program_asm, program_asm_size);
= assemble_lines_with_labels(program, program_asm, program_asm_size);
printf("done!\n");
printf("program size = %d\n", program_size);

View File

@ -1,5 +1,6 @@
#include "vm.h"
#include "common/arch.h"
#include "common/op_str.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>