📄 x86dos.c
字号:
#define X86_LINUX#include <stdio.h>#include "common.h"#include "symtab.h"#include "error.h"#include "x86.h"#ifdef _MSDOS_#include <dos.h>#elif defined __linux__#include <time.h>#endif#include _YTAB_H_#define MAX_LOOP_LEVEL 16#define STMT_STACK_SIZE 64#define MAX_CALL_LEVEL 16static symtab *rtn =NULL;static symbol *arg = NULL;static Symbol p;static Symtab ptab;static void emit_dos_write1(int arg_type);static void emit_dos_sqrt(int arg_type);static void emit_dos_odd(int arg_type);static void emit_dos_abs(int arg_type);static void emit_dos_sqr(int arg_type);static void emit_dos_read1(int arg_type);static void emit_dos_writeln(int arg_type);static int gen_level = 0;static void emit_dos_program_head();static void emit_dos_program_prologue(symtab *);static void emit_dos_program_epilogue(symtab *);static void emit_dos_main_prologue(symtab *);static void emit_dos_main_epilogue(symtab *);static void emit_dos_routine_prologue(symtab *);static void emit_dos_routine_epilogue(symtab *);static void emit_dos_local_args(symtab *);static void emit_dos_dos_push_op(Type ptype);static void emit_dos_load_value(symbol *);static void do_dos_function_assign(symtab *,int);static void do_dos_procedure_call(symtab *);static void do_dos_assign(symbol *, int);static void do_dos_expression(Type, int);static void do_dos_negate(symbol *);static void do_dos_expr(Type, int);static void do_dos_term(Type, int);static void do_dos_factor(symbol *);static void do_dos_array_factor(symbol *);static void do_dos_record_factor(symbol *, symbol *);static void do_dos_first_arg(int);static int emit_dos_address = 0;#define MICROSOFT_MASMstatic void do_dos_sys_routine(int routine_id, int arg_type){ switch(routine_id) { case fABS: emit_dos_abs(arg_type); break; case fODD: emit_dos_odd(arg_type); break; case fPRED: fprintf(codfp, "\t\tdec\tax\n"); break; case fSQR: emit_dos_sqr(arg_type); break; case fSQRT: emit_dos_sqrt(arg_type); break; case fSUCC: fprintf(codfp, "\t\tinc\tax\n"); break; case pREAD: emit_dos_read1(arg_type); break; case pREADLN: emit_dos_read1(arg_type); break; case pWRITE: emit_dos_write1(arg_type); break; case pWRITELN: emit_dos_writeln(arg_type); break; default: break; }}static void emit_dos_read1(int arg_type){ fprintf(codfp, "\t\tpush\tax\n"); fprintf(codfp, "\t\tpush\tbp\n"); switch(arg_type) { case TYPE_REAL: break; case TYPE_INTEGER: fprintf(codfp, "\t\tcall\t_read_int\n"); break; case TYPE_STRING: fprintf(codfp, "\t\tcall\t_read_string\n"); break; case TYPE_CHAR: fprintf(codfp, "\t\tcall\t_read_char\n"); break; case TYPE_BOOLEAN: default: parse_error("operand type do not match operator.", ""); break; }}static void emit_dos_write1(int arg_type){ switch(arg_type) { case TYPE_BOOLEAN: case TYPE_INTEGER: fprintf(codfp, "\t\tpush\tax\n"); fprintf(codfp, "\t\tpush\tbp\n"); fprintf(codfp, "\t\tcall\t_write_int\n"); break; case TYPE_CHAR: fprintf(codfp, "\t\tmov\tdl,al\n"); fprintf(codfp, "\t\tmov\tah,2\n"); fprintf(codfp, "\t\tint\t21h\n"); break; case TYPE_STRING: fprintf(codfp, "\t\tpush\tax\n"); fprintf(codfp, "\t\tpush\tbp\n"); fprintf(codfp, "\t\tcall\t_write_string\n"); break; default: break; }}static void emit_dos_writeln(int arg_type){ switch(arg_type) { case TYPE_BOOLEAN: case TYPE_INTEGER: fprintf(codfp, "\t\tpush\tax\n"); fprintf(codfp, "\t\tpush\tbp\n"); fprintf(codfp, "\t\tcall\t_writeln_int\n"); break; case TYPE_CHAR: fprintf(codfp, "\t\tmov\tdl,al\n"); fprintf(codfp, "\t\tmov\tah,2\n"); fprintf(codfp, "\t\tint\t21h\n"); fprintf(codfp, "\t\tmov\tdl,13\n"); fprintf(codfp, "\t\tint\t21h\n"); fprintf(codfp, "\t\tmov\tdl,10\n"); fprintf(codfp, "\t\tint\t21h\n"); break; case TYPE_STRING: fprintf(codfp, "\t\tpush\tax\n"); fprintf(codfp, "\t\tpush\tbp\n"); fprintf(codfp, "\t\tcall\t_writeln_string\n"); break; default: break; }}static void emit_dos_abs(int arg_type){ fprintf(codfp, "\t\tpush\tbp\n"); switch(arg_type) { case TYPE_BOOLEAN: case TYPE_INTEGER: fprintf(codfp, "\t\tcall\t_abs_int\n"); break; case TYPE_CHAR: fprintf(codfp, "\t\txor\tah,ah\n"); fprintf(codfp, "\t\tcall\t_abs_int\n"); break; default: break; }}static void emit_dos_sqr(int arg_type){ fprintf(codfp, "\t\tpush\tbp\n"); switch(arg_type) { case TYPE_BOOLEAN: case TYPE_INTEGER: fprintf(codfp, "\t\tcall\t_sqr_int\n"); break; case TYPE_CHAR: fprintf(codfp, "\t\txor\tah,ah\n"); fprintf(codfp, "\t\tcall\t_sqr_int\n"); break; default: break; }}static void emit_dos_odd(int arg_type){ fprintf(codfp, "\t\tpush\tbp\n"); switch(arg_type) { case TYPE_BOOLEAN: case TYPE_INTEGER: fprintf(codfp, "\t\tcall\t_odd_int\n"); break; case TYPE_CHAR: fprintf(codfp, "\t\txor\tah,ah\n"); fprintf(codfp, "\t\tcall\t_odd_int\n"); break; default: break; }}static void emit_dos_sqrt(int arg_type){ fprintf(codfp, "\t\tpush\tbp\n"); switch(arg_type) { case TYPE_BOOLEAN: case TYPE_INTEGER: fprintf(codfp, "\t\tcall\t_sqrt_int\n"); break; case TYPE_CHAR: fprintf(codfp, "\t\txor\tah,ah\n"); fprintf(codfp, "\t\tcall\t_sqrt_int\n"); break; default: break; }}static void emit_dos_program_prologue(symtab *ptab){#ifndef MICROSOFT_MASM fprintf(codfp, " \n;alloc stack space\n"); fprintf(codfp, " \t\tdb\t%xh dup(?)\n" ,STACK_SEG_SIZE); fprintf(codfp,"\n_DATA\t\tends");#endif fprintf(codfp,"\n\n;---program %s ---",ptab->name);#ifndef MICROSOFT_MASM fprintf(codfp,"\n\n_TEXT\t\tsegment\tpublic\n\n");#else fprintf(codfp,"\n\n.CODE\n");#endif fprintf(codfp,"\t\tinclude\tx86rtl.inc\n\n"); fprintf(codfp,"%s\tequ\tword ptr [bp+04h]\n" ,LABEL_SLINK); fprintf(codfp,"%s\tequ\tword ptr [bp-04h]\n", LABEL_RETVAL); fprintf(codfp,"%s\tequ\tword ptr [bp-02h]\n", LABEL_HIRETVAL); emit_dos_program_head();#ifndef MICROSOFT_MASM fprintf(datfp, " \n_DATA\t\tsegment\tpublic\n");#else fprintf(datfp, " \n.DATA\n");#endif}/* char datname[]; */static void emit_dos_program_head(){#ifdef _MSDOS_ struct dosdate_t d; struct dosdate_t t; _dos_getdate(&d); _dos_gettime(&t); fprintf(datfp,";%s\n:%02d:%02d:%02d/%d/%d/%d\n", t.hour,t.minute,t.second,d.month,d.day,d.year);#elif defined __linux__ time_t now; struct tm *tv; time(&now); tv = gmtime(&now); fprintf(datfp, ";%04d/%02d/%02d\n;%02d:%02d:%02d\n", tv->tm_year + 100, tv->tm_mon, tv->tm_mday, tv->tm_hour, tv->tm_min, tv->tm_sec);#endif fprintf(datfp,";\n"); fprintf(datfp,";SPL Compiler Ver %s\n",_PC_VER_); fprintf(datfp,";\n");#ifdef MICROSOFT_MASM fprintf(datfp,";small model\n"); fprintf(datfp,".MODEL SMALL\n"); fprintf(datfp,"\n;set stack size\n"); fprintf(datfp,".STACK %xh\n", STACK_SEG_SIZE);#endif}static void emit_dos_program_epilogue(symtab *ptab){ symbol *p;#ifndef MICROSOFT_MASM fprintf(codfp,"\n_TEXT\t\tends\n"); fprintf(codfp,"\t\tend\tstart\n\n");#else fprintf(codfp,"\n\n\t\t.STARTUP\n"); fprintf(codfp,"\t\tcall _main\n"); fprintf(codfp,"\n\n\t\t.EXIT\n"); fprintf(codfp,"\t\tend\n\n");#endif fprintf(datfp,"\n;global variables\n"); for(p = ptab->locals; p; p = p->next) { switch (p->type->type_id) { case TYPE_CHAR: fprintf(datfp,"%s\t\tdb\t",p->rname); break; case TYPE_BOOLEAN: case TYPE_INTEGER: fprintf(datfp,"%s\t\tdw\t",p->rname); break; case TYPE_REAL: fprintf(datfp,"%s\t\tdd\t",p->rname); break; case TYPE_STRING: fprintf(datfp,"%s\t\tdb\t%s\n",p->rname, p->v.s); fprintf(datfp,"\t\tdb\t'$'\n"); break; case TYPE_ARRAY: if(p->type_link->last->type->type_id == TYPE_INTEGER || p->type_link->last->type->type_id == TYPE_BOOLEAN) fprintf(datfp,"%s\t\tdw\t0%xh dup (?)\n" ,p->rname,p->type_link->num_ele); else if(p->type_link->last->type->type_id == TYPE_CHAR) fprintf(datfp,"%s\t\tdb\t0%xh dup (?)\n" ,p->rname,p->type_link->num_ele); else parse_error("complex array element not supported",""); if(p->defn != DEF_CONST) continue; break; case TYPE_RECORD: fprintf(datfp,"%s\t\tdb\t0%xh dup (?)\n" ,p->rname,p->type_link->size); continue; default: break; } if (p->defn == DEF_CONST) { switch(p->type->type_id) { case TYPE_CHAR: fprintf(datfp,"'%c'\n",p->v.c); break; case TYPE_INTEGER: if (p->v.i >= 0) fprintf(datfp, "0%xh\n", p->v.i); break; case TYPE_REAL: fprintf(datfp, "%g\n", p->v.f); break; case TYPE_STRING: break; default: fprintf(datfp,"?\n"); } } else fprintf(datfp,"?\n"); }}static void emit_dos_main_prologue(symtab *ptab){ fprintf(codfp,"\n\n; --- main routine ----\n");#ifndef MICROSOFT_MASM fprintf(codfp,"_main\t\tproc\tfar\n"); fprintf(codfp,"\t\tassume\tcs:_TEXT,ds:_DATA\n"); fprintf(codfp,"start:\n"); fprintf(codfp,"\t\tpush\tds\n"); fprintf(codfp,"\t\tsub\tax,ax\n"); fprintf(codfp,"\t\tpush\tax\n"); fprintf(codfp,"\t\tmov\tax,_DATA\n"); fprintf(codfp,"\t\tmov\tds,ax\n");#else fprintf(codfp,"_main\t\tproc\tnear\n"); fprintf(codfp,"\t\tassume\tcs:_TEXT,ds:_DATA\n"); fprintf(codfp,"\t\tmov\tax,_DATA\n"); fprintf(codfp,"\t\tmov\tds,ax\n");#endif}static void emit_dos_main_epilogue(symtab *ptab){ fprintf(codfp,"\t\tret\n"); fprintf(codfp,"_main\t\tendp\n");}static void emit_dos_routine_prologue(symtab *ptab){ if(ptab->defn == DEF_PROG) return; fprintf(codfp,"\n\n; routine : %s \n",ptab->name); emit_dos_local_args(ptab); fprintf(codfp,";routine code\n"); fprintf(codfp,"%s\t\tproc\n", ptab->rname); fprintf(codfp,"\t\tassume\tcs:_TEXT,ds:_DATA\n"); fprintf(codfp,"\t\tmov\tax,_DATA\n"); fprintf(codfp,"\t\tmov\tds,ax\n"); fprintf(codfp,"\t\tpush\tbp\n"); fprintf(codfp,"\t\tmov\tbp,sp\n"); if(ptab->defn == DEF_FUNCT) fprintf(codfp,"\t\tsub\tsp, 4\n"); fprintf(codfp,"\t\tsub\tsp,%04xh\n",ptab->local_size);}static void emit_dos_local_args(symtab *ptab){ symbol *p; char tp[10]; fprintf(codfp,";local variables in %s\n",ptab->name); for(p = ptab->locals; p->next; p = p->next) { switch(p->type->type_id) { case TYPE_CHAR: sprintf(tp, "byte ptr"); break; case TYPE_INTEGER: case TYPE_BOOLEAN: sprintf(tp, "word ptr"); break; case TYPE_REAL: sprintf(tp, "dword ptr");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -