⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 st.c

📁 一个C style Assembler的source code
💻 C
字号:
#include <stdlib.h>#include <stdio.h>#include <ctype.h>#include <string.h>#include "io.h"#include "ex.h"#include "op.h"#include "res.h"#define MAX_ST 20typedef enum { BotS, IfS, ElseS, GroupS } StTag;byte Active;int Phase;StTag SStack[MAX_ST], *SP;byte IStack[MAX_ST], *IP;void PUSH(StTag Tag) {   if (SP >= SStack + MAX_ST) FATAL("Statement too complex");   *SP++ = Tag;}void SetColon(byte Glo, Symbol Sym) {   if (!Active) return;   if (Sym->Defined) {      if (*Sym->Name != '#') {         ERROR("Attempting to redefine %s.", Sym->Name); return;      } else if (Glo) {         ERROR("Attempting to make local label global."); return;      } else {         Sym->Address = 1, Sym->Global = 0, Sym->Variable = 1;      }   } else if (Sym->Global) {      if (!Glo) {         ERROR("Symbol %s already declared as external.", Sym->Name); return;      } else if (!Sym->Address) {         ERROR("Symbol %s already declared as number.", Sym->Name); return;      } else if (Sym->Seg->Type != SegP->Type) {         ERROR("Type mismatch: %s.", Sym->Name); return;      }   } else      Sym->Address = 1, Sym->Global = Glo, Sym->Variable = 0;   Sym->Defined = 1, Sym->Seg = SegP, Sym->Offset = LOC;}void SetVar(byte Glo, Symbol Sym, Exp E) {   if (!Active) return;   if (Sym->Defined && !Sym->Variable)      ERROR("Symbol %s already defined as constant.", Sym->Name);   else if (Glo)      ERROR("Variables cannot be made global.");   else if (Sym->Global)      ERROR("Symbol %s already declared as external.", Sym->Name);   else if (!Sym->Defined) {      if (E->Tag == AddrX)         Sym->Address = 1, Sym->Seg = SEG(E), Sym->Offset = OFFSET(E);      else         Sym->Address = 0, Sym->Offset = VALUE(E);      Sym->Variable = 1, Sym->Defined = 1;   } else if (Sym->Address) {      if (E->Tag != AddrX)         Sym->Seg = SegTab + Sym->Seg->Type, Sym->Offset = VALUE(E);               else if (SEG(E)->Type != Sym->Seg->Type)         ERROR("Type mismatch: %s.", Sym->Name);      else         Sym->Seg = SEG(E), Sym->Offset = OFFSET(E);   } else if (E->Tag == AddrX) {      if (SEG(E)->Rel)         ERROR("Symbol %s cannot be set to relative address.", Sym->Name);      else         Sym->Offset = SEG(E)->Base + OFFSET(E);   } else      Sym->Offset = VALUE(E);}void SetConst(byte Glo, byte Addr, byte Type, Symbol Sym, Exp E) {   if (!Active) return;   if (Addr && E->Tag == AddrX && SEG(E)->Type != Type) {      ERROR("Expression type does not match."); return;   } else if (Sym->Defined) {      ERROR("Symbol %s already defined.", Sym->Name); return;   } else if (!Sym->Global)      Sym->Global = Glo, Sym->Variable = 0, Sym->Address = (E->Tag == AddrX);   else if (!Glo) {      ERROR("Symbol %s already declared as external.", Sym->Name); return;   } else if (Sym->Address) {      if (Addr && Sym->Seg->Type != Type) {         ERROR("Symbol %s's type does not match.", Sym->Name); return;      } else if (E->Tag != AddrX) {         Sym->Defined = 1, Sym->Offset = VALUE(E); return;      } else if (SEG(E)->Type != Sym->Seg->Type) {         ERROR("Type mismatch: %s.", Sym->Name); return;      }   } else if (Addr) {      ERROR("Symbol %s already declared as external number.", Sym->Name);      return;   } else if (E->Tag == AddrX) {      if (SEG(E)->Rel) {         ERROR("Symbol %s cannot be equated to relative address.", Sym->Name);         return;      } else {         Sym->Defined = 1, Sym->Offset = SEG(E)->Base + OFFSET(E); return;      }   }   Sym->Defined = 1;   if (E->Tag == AddrX)      Sym->Seg = SEG(E), Sym->Offset = OFFSET(E);   else      Sym->Offset = VALUE(E);}FILE *OpenObj(char *Obj) {   FILE *FP; word MAGIC = 0x55aa;   unsigned long L = 0; int I;   FP = fopen(Obj, "wb");   if (FP == 0) return 0;   PutW(MAGIC, FP);   for (I = 0; I < 8; I++) PutL(L, FP); /* Empty the header */   fclose(FP);   FP = fopen(Obj, "rb+");   if (FP == 0) return 0;   fseek(FP, 34L, SEEK_SET); /* Skip the header */   return FP;}void Assemble(char *Path) {   Lexical L; Exp E; byte Glo, Addr, Type; Symbol Label;   Phase = 0;   SymInit(), FileInit(), SegInit(), ExpInit(), ResInit();   IP = IStack, SP = SStack;   Active = 1; RegInit(); OpenF(Path); L = Scan();START:   if (L == 0) { EndSeg(); return; }   PUSH(BotS);STATEMENT:   StartLine = Line, StartF = CurF;   switch (L) {      case IF:         L = Scan();         if (L != LPAR) ERROR("Missing '(' in 'if (...)'"); else Scan();         E = Parse(0);         PUSH(IfS), *IP++ = Active;         if (Active) Active = VALUE(E);         L = OldL;         if (L != RPAR) ERROR("Missing ')' in 'if (...)'."); else L = Scan();      goto STATEMENT;      case LCURL:         L = Scan();         if (L == RCURL) { L = Scan(); goto END_ST; }         PUSH(GroupS);      goto STATEMENT;      case SEMI: L = Scan(); goto END_ST;      case RB:         Scan(), InSemi = 1, E = Parse(0);         Space(VALUE(E));      goto SEM;      case RW:         Scan(), InSemi = 1, E = Parse(0);         Space(2*VALUE(E));      goto SEM;      case SEG:         L = Scan();         if (L != TYPE) { ERROR("Expected segment type."); goto PURGE; }         if (Value != CODE && Value != XDATA && Value != DATA) {            ERROR("Only code, xdata, or data segments allowed."); goto PURGE;         }         Type = Value;         InSemi = 1, L = Scan();         if (L == ORG) { InSemi = 0; goto DoOrg; }         if (Active) EndSeg(), StartSeg(Type, 1, 0);      goto SEM;      case ORG:         Type = SegP->Type;      DoOrg:         Scan(), InSemi = 1, E = Parse(0);         if (Active) EndSeg(), StartSeg(Type, 0, VALUE(E));      goto SEM;      case INCLUDE: {         char *S;         L = Scan();         if (L != STRING) FATAL("Missing filename in 'include'.");         S = CopyS(Text);         InSemi = 1, L = Scan();         if (L != SEMI) FATAL("Missing ';' after include statement.");         OpenF(S), free(S);         InSemi = 0, L = Scan();      }      goto END_ST;      case GLOBAL:         Glo = 1;         L = Scan();         if (L != SYMBOL) {            ERROR("Expected symbol after 'global'"); goto PURGE;         }      goto DEFINE;      case SYMBOL:         Glo = 0;      DEFINE:         Label = Sym; L = Scan();         switch (L) {            case COLON:               SetColon(Glo, Label);               InSemi = 1, L = Scan(), InSemi = 0;            goto STATEMENT;            case SET:               Scan(), InSemi = 1, E = Parse(1), SetVar(Glo, Label, E);            goto SEM;            case TYPE: Type = Value, Addr = 1; goto DoEqu;            case EQU: Type = 0, Addr = 0;            DoEqu:               Scan(), InSemi = 1, E = Parse(1);               SetConst(Glo, Addr, Type, Label, E);            goto SEM;            default: ERROR("Undefined symbol: %s.", Label->Name); goto PURGE;         }      break;      case EXTERN:         L = Scan();         if (L == EQU) Addr = 0;         else if (L == TYPE) Addr = 1, Type = Value;         else {            ERROR("Expected type or 'equ' after 'extern'."); goto PURGE;         }         InSemi = 1;         do {            L = Scan();            if (L != SYMBOL) {               ERROR("Expected symbol in 'extern'"); goto PURGE;            }            if (Active) {               if (Sym->Global) {                  byte Addr1 = Sym->Address;                  if (!Addr && Addr1)                     ERROR("Redeclaring number %s as address.", Sym->Name);                  else if (Addr && !Addr1)                     ERROR("Redeclaring address %s as number.", Sym->Name);                  else if (Addr && Addr1 && Type != Sym->Seg->Type)                     ERROR("Type mismatch: %s.", Sym->Name);               } else if (Sym->Defined)                  ERROR("Redeclaring local symbol %s as external.", Sym->Name);               else {                  Sym->Global = 1;                  if (Addr) Sym->Address = 1, Sym->Seg = SegTab + Type;               }            }            Scan();         } while (OldL == COMMA);      goto SEM;      case DB:         InSemi = 1;         do {            L = Scan();            if (L == STRING) PString(Text), Scan();            else Reloc(0, 'b', Parse(2));         } while (OldL == COMMA);      goto SEM;      case DW:         InSemi = 1;         do            Scan(), Reloc(0, 'w', Parse(2));         while (OldL == COMMA);      goto SEM;      case END:         if (Active) { EndSeg(); return; }         InSemi = 1, Scan();      goto SEM;      case MNEMONIC: InSemi = 1, ParseArgs((byte)Value); goto SEM;      default: ERROR("Syntax error"); goto PURGE;   }PURGE:   InSemi = 1;   while (L != SEMI) {      if (L == 0) { InSemi = 0; goto END_ST; }      L = Scan();   }SEM:   InSemi = 0; L = OldL;   if (L != SEMI) ERROR("Missing ';'"); else L = Scan();END_ST:   switch (*--SP) {      case BotS: goto START;      case IfS:         if (L == ELSE) {            if (IP == IStack || IP[-1]) Active = !Active;            *SP++ = ElseS, L = Scan(); goto STATEMENT;         }      case ElseS: EndIf:         if (*--IP && !Active) {            Active = 1;            if (L == SYMBOL) Sym = LookUp(Text);         }      goto END_ST;      case GroupS:         if (L == RCURL) { L = Scan(); goto END_ST; }         if (L == 0) { ERROR("Missing '}'."); goto END_ST; }         *SP++ = GroupS;      goto STATEMENT;   }}static void Purge(void) {   Symbol Sym, NextS; Exp E, NextE; char **F;   for (Sym = NIL->Next[0]; Sym != NIL; Sym = NextS)      NextS = Sym->Next[0], free(Sym->Name), free(Sym);   for (F = FileTab; F < FileTab + Files; F++) free(*F);   free(FileTab);   free(NIL);   for (E = ExpHead; E != 0; E = NextE) NextE = E->Next, free(E);   free(RTab);}void Generate(void) {   Symbol S; Segment Seg; Exp E; Item IP; word Value, File; Gap G;   unsigned long SegLoc, Segs, Gaps, Syms, Exps, Relocs, Sum;   Phase = 1;   SegLoc = ftell(OutF), Segs = SegP - SegTab, Gaps = GapP - GapTab;   for (IP = RTab; IP < RTab + RCur; IP++) Resolve(IP);   fseek(OutF, SegLoc, SEEK_SET); /* Skip the code image */   for (File = 0; File < Files; File++) {      word L = strlen(FileTab[File]);      PutW(L, OutF), fwrite(FileTab[File], 1, L, OutF);   }   for (Seg = SegTab + TYPES; Seg < SegP; Seg++) {      word U = (Seg->Rel&1) << 8 | Seg->Type&0xff;      PutW(Seg->Line, OutF), PutW(Seg->File, OutF),      PutW(U, OutF), PutW(Seg->Size, OutF),      PutW(Seg->Base, OutF), PutL(Seg->Loc, OutF);   }   for (G = GapTab; G < GapP; G++)      PutW(G->Seg - SegTab, OutF), PutW(G->Offset, OutF), PutW(G->Size, OutF);   for (Syms = 0, S = NIL->Next[0]; S != NIL; S = S->Next[0])   if (S->Map || S->Global && S->Defined) {      byte B = (S->Global&1) << 3  | (S->Defined&1) << 2 |               (S->Address&1) << 1 | (S->Variable&1);      word U = S->Seg - SegTab, L = strlen(S->Name);      if (!S->Global && !S->Defined)         ERROR("Undefined symbol: %s.", S->Name);      S->Index = Syms++;      PutB(B, OutF), PutW(U, OutF), PutW(S->Offset, OutF), PutW(L, OutF);      if (L > 0) fwrite(S->Name, 1, L, OutF);   }   for (Exps = 0, E = ExpHead; E != 0; E = E->Next)   if (E->Map) {      byte Tag = E->Tag, Op; word U;      E->Hash = Exps++;      PutW(E->Line, OutF), PutW(E->File, OutF), PutB(Tag, OutF);      switch (Tag) {         case NumX: PutW(VALUE(E), OutF); break;         case AddrX:            PutW(SEG(E) - SegTab, OutF), PutW(OFFSET(E), OutF);         break;         case SymX: PutW(SYM(E)->Index, OutF); break;         case UnX:            Op = OP(E);            PutB(Op, OutF), PutW(ARG1(E)->Hash, OutF);         break;         case BinX:            Op = OP(E);            PutB(Op, OutF), PutW(ARG1(E)->Hash, OutF),            PutW(ARG2(E)->Hash, OutF);         break;         case CondX:            PutW(ARG1(E)->Hash, OutF), PutW(ARG2(E)->Hash, OutF),            PutW(ARG3(E)->Hash, OutF);         break;      }   }   for (Relocs = 0, IP = RTab; IP < RTab + RCur; IP++)   if (IP->Map) {      word U = IP->Seg - SegTab;      Relocs++;      PutW(IP->Line, OutF), PutW(IP->File, OutF),      PutB(IP->Tag, OutF), PutW(IP->E->Hash, OutF),      PutW(U, OutF),      PutW(IP->Offset, OutF);   }   fseek(OutF, 2L, SEEK_SET); /* Do the header */   PutL(SegLoc, OutF), PutL(Files, OutF), PutL(Segs, OutF),   PutL(Gaps, OutF), PutL(Syms, OutF), PutL(Exps, OutF), PutL(Relocs, OutF);   Sum = SegLoc + Files + Segs + Gaps + Syms + Exps + Relocs;   PutL(Sum, OutF);   fclose(OutF);   Purge();}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -