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

📄 ex.c

📁 一个C style Assembler的source code
💻 C
字号:
#include <stdlib.h>#include <stdio.h>#include <stdarg.h>#include "io.h"#include "ex.h"#include "st.h"#include "res.h"/* Derived from the syntax:   Ex = primary | unary Ex | Ex binary Ex | Ex "?" Ex ":" Ex | "(" Ex ")".   with the usual C-like precedence rules. */Exp ExpHead;static Exp ExpTail;static Exp ExpHash[0x100];void ExpInit(void) {   int H;   ExpTail = ExpHead = 0;   for (H = 0; H < 0x100; H++) ExpHash[H] = 0;}static byte Direct = 2; /* 0 = Absolute, 1 = Relative, 2 = Undefined */#define STACK_MAX 100typedef enum { BOT, PAR, COND, ELS, BIN, UN } StackTag;static StackTag TStack[STACK_MAX], *TP;static Lexical OStack[STACK_MAX], *OP;static struct Exp EStack[STACK_MAX], *EP;static Exp AStack[STACK_MAX], *AP;static void PUSH(StackTag Tag) {   if (TP >= TStack + STACK_MAX)      FATAL("Expression too complex ... aborting.");   *TP++ = Tag;}static void PutE(Exp E) { if (Direct < 2) EP++; else *AP++ = E; }static Exp GetE(void) { return (Direct < 2)? --EP: *--AP; }void MarkExp(Exp E) {   if (E->Map) return;   E->Map = 1;   switch (E->Tag) {      case NumX: case AddrX: break;      case SymX: SYM(E)->Map = 1; break;      case CondX:         MarkExp(ARG3(E));      case BinX:         MarkExp(ARG2(E));      case UnX:         MarkExp(ARG1(E));      break;   }}Exp EvalExp(Exp E) {   ExpTag Tag = E->Tag;   Symbol Sym; Lexical Op; Exp A, B, C, E1; byte H, Bs;   Segment Seg; word Offset, Value, vB;   if (Phase == 1) {      if (E->Mark) return E;      StartLine = E->Line, StartF = E->File;   }   switch (Tag) {      case NumX: Value = VALUE(E); break;      case AddrX: Seg = SEG(E), Offset = OFFSET(E); break;      case SymX:         Sym = SYM(E);         if (!Sym->Defined) break;         else if (Sym->Address)            Tag = AddrX, Seg = Sym->Seg, Offset = Sym->Offset;         else            Tag = NumX, Value = Sym->Offset;      break;      case UnX:         Op = OP(E), A = ARG1(E);         if (Phase == 1) A = EvalExp(A);         if (Op == PLUS) return A;         switch (A->Tag) {            case AddrX:               ERROR("Address cannot be used with prefix operator.");               Tag = NumX; Value = SEG(A)->Base + OFFSET(A);            break;            case NumX: Tag = NumX; Value = VALUE(A); break;         }         if (Tag == NumX) switch (Op) {            case HIGH: Value = (Value >> 8)&0xff; break;            case LOW: Value = Value&0xff; break;            case NOT_NOT: Value = !Value; break;            case NOT: Value = ~Value; break;            case MINUS: Value = -Value; break;         }      break;      case BinX:         Op = OP(E), A = ARG1(E), B = ARG2(E);         if (Phase == 1) A = EvalExp(A), B = EvalExp(B);         if (Op == PLUS) {            if (A->Tag == NumX && B->Tag == NumX) {               Tag = NumX, Value = VALUE(A) + VALUE(B);            } else if (A->Tag == NumX && B->Tag == AddrX) {               Tag = AddrX, Seg = SEG(B), Offset = VALUE(A) + OFFSET(B);            } else if (A->Tag == AddrX && B->Tag == NumX) {               Tag = AddrX, Seg = SEG(A), Offset = OFFSET(A) + VALUE(B);            } else if (A->Tag == AddrX && B->Tag == AddrX) {               ERROR("Illegal combination: address + address");               Tag = AddrX, Seg = SEG(A), Offset = OFFSET(A) + OFFSET(B);            }         } else if (Op == MINUS) {            if (A->Tag == NumX && B->Tag == NumX) {               Tag = NumX, Value = VALUE(A) - VALUE(B);            } else if (A->Tag == NumX && B->Tag == AddrX) {               ERROR("Illegal combination: number - address");               Tag = NumX, Value = VALUE(A) - (SEG(B)->Base + OFFSET(B));            } else if (A->Tag == AddrX && B->Tag == NumX) {               Tag = AddrX, Seg = SEG(A), Offset = OFFSET(A) - VALUE(B);            } else if (A->Tag == AddrX && B->Tag == AddrX) {               if (SEG(A)->Type != SEG(B)->Type) {                  ERROR("Addresses of different types cannot be subtracted.");                  Tag = AddrX, Seg = SEG(A), Offset = OFFSET(A) - OFFSET(B);               } else if (SEG(A) == SEG(B))                  Tag = NumX, Value = OFFSET(A) - OFFSET(B);            }         } else if (Op == DOT) {            Tag = AddrX, Seg = SegTab + BIT;            switch (A->Tag) {               case NumX:                  Offset = VALUE(A);               XX:                  if ((Offset&0xfff0) == 0x20) Offset = (Offset - 0x20) << 3;                  else if ((Offset&0xff87) != 0x80)                     ERROR("Register in reg.bit not bit addressible."),                     Offset = 0;               break;               case AddrX:                  if (SEG(A)->Type != DATA && SEG(A)->Type != SFR)                     ERROR("Address of wrong type in reg.pos"), Offset = 0;                  else if (SEG(A)->Rel) {                     Tag = BinX; break;                  } else {                     Offset = SEG(A)->Base + OFFSET(A);                     if (SEG(A)->Type == DATA && Offset >= 0x80)                        ERROR("Indirect registers are not bit addressible."),                        Offset = 0;                  }               goto XX;               default: Tag = BinX; break;            }            if (Tag == AddrX) switch (B->Tag) {               case NumX:                  vB = VALUE(B);                  if (vB >= 8)                     ERROR("Bit position out of range."), vB &= 7;               break;               case AddrX:                  ERROR("Illegal combination: reg.bit"), vB = 0;               break;               default: Tag = BinX; break;            }            if (Tag == AddrX) Offset += vB;         } else {            Tag = NumX;            if (A->Tag == AddrX || B->Tag == AddrX)               ERROR("Address cannot be used with infix operator.");            else if (A->Tag != NumX && B->Tag != NumX) Tag = BinX;            if (Tag == NumX) {               Value = A->Tag == NumX? VALUE(A): OFFSET(A),               vB = B->Tag == NumX? VALUE(B): OFFSET(B);               switch (Op) {                  case BY: Value = (Value << 8) | (vB&0xff); break;                  case OR_OR: if (vB) Value = 1; break;                  case AND_AND: if (!vB) Value = 0; break;                  case OR: Value |= vB; break;                  case XOR: Value ^= vB; break;                  case AND: Value &= vB; break;                  case SHL: Value <<= vB; break;                  case SHR: Value >>= vB; break;                  case MULT: Value *= vB; break;                  case EQ: Value = Value == vB; break;                  case NE: Value = Value != vB; break;                  case LE: Value = Value <= vB; break;                  case LT: Value = Value < vB; break;                  case GE: Value = Value >= vB; break;                  case GT: Value = Value > vB; break;                  case DIV:                     if (vB == 0) ERROR("Division by 0."), Value = -1;                     else Value /= vB;                  break;                  case MOD:                     if (vB == 0) ERROR("Modulo by 0."), Value = -1;                     else Value %= vB;                  break;               }            }         }      break;      case CondX:         A = ARG1(E), B = ARG2(E), C = ARG3(E);         if (Phase == 1) A = EvalExp(A), B = EvalExp(B), C = EvalExp(C);         if (A->Tag == AddrX) {            ERROR("Address cannot appear in: x? x: x"); return C;         } else if (A->Tag != NumX) Tag = CondX;         else return EvalExp((VALUE(A))? B: C);      break;   }   if (Direct < 2) {      if (Tag == AddrX) {         if (Direct == 0) {            if (Seg->Rel) ERROR("Relative address cannot be used here");            Tag = NumX, Value = Seg->Base + Offset;         }      } else {         if (Tag == SymX)            ERROR("Undefined symbol: %s", Sym->Name), Tag = NumX, Value = 0;         else if (Tag != NumX)            ERROR("Undefined expression"), Tag = NumX, Value = 0;      }      if (Tag == NumX)         EP->Tag = NumX, VALUE(EP) = Value;      else         EP->Tag = AddrX, SEG(EP) = Seg, OFFSET(EP) = Offset;      return EP;   }   Bs = Seg - SegTab;   if (Phase == 1) E1 = E;   switch (Tag) {      case NumX:         H = (Value^(Value>>6)^(Value>>12))&0x3f;         for (E = ExpHash[H]; E != 0; E = E->Tail)            if (Value == VALUE(E)) return E;      break;      case AddrX:         H = (Bs^(Bs>>6)^Offset^(Offset>>6)^(Offset>>12))&0x3f|0x40;         for (E = ExpHash[H]; E != 0; E = E->Tail)            if (Seg == SEG(E) && Offset == OFFSET(E)) return E;      break;      case SymX: {         char *S;         for (H = 0, S = Sym->Name; *S != '\0'; S++) H ^= *S;         H = H&0x3f|0x80;         for (E = ExpHash[H]; E != 0; E = E->Tail)            if (Sym == SYM(E)) return E;      }      break;      case UnX:         H = (Op^(Op>>6)^A->Hash)&0xf|0xe0;         for (E = ExpHash[H]; E != 0; E = E->Tail)            if (Op == OP(E) && A == ARG1(E)) return E;      break;      case BinX:         H = (Op^(Op>>6)^A->Hash^B->Hash)&0x1f|0xc0;         for (E = ExpHash[H]; E != 0; E = E->Tail)            if (Op == OP(E) && A == ARG1(E) && B == ARG2(E)) return E;      break;      case CondX:         H = (A->Hash^B->Hash^C->Hash)&0xf|0xf0;         for (E = ExpHash[H]; E != 0; E = E->Tail)            if (A == ARG1(E) && B == ARG2(E) && C == ARG3(E)) return E;      break;   }   if (Phase == 1) E = E1, E->Mark = 1;   else {      E = (Exp)Allocate(sizeof *E);      E->Hash = H, E->Tail = ExpHash[H], ExpHash[H] = E;      E->Next = 0, E->Map = 0,      E->Line = StartLine, E->File = StartF,      E->Mark = (Phase == 0)? 0: 1;      if (ExpHead == 0) ExpHead = E; else ExpTail->Next = E;      ExpTail = E;   }   switch (E->Tag = Tag) {      case NumX: VALUE(E) = Value; break;      case AddrX: SEG(E) = Seg, OFFSET(E) = Offset; break;      case SymX: SYM(E) = Sym; break;      case UnX: OP(E) = Op, ARG1(E) = A; break;      case BinX: OP(E) = Op, ARG1(E) = A, ARG2(E) = B; break;      case CondX: ARG1(E) = A, ARG2(E) = B, ARG3(E) = C; break;   }   return E;}static struct Exp EBuf;Exp MakeExp(ExpTag Tag, ...) {   va_list AP; Exp E = &EBuf;   if (!Active) return 0;   va_start(AP, Tag);   switch (E->Tag = Tag) {      case NumX: VALUE(E) = (word)va_arg(AP, unsigned); break;      case AddrX:         SEG(E) = va_arg(AP, Segment), OFFSET(E) = (word)va_arg(AP, unsigned);      break;      case SymX: SYM(E) = va_arg(AP, Symbol); break;      case UnX:         OP(E) = va_arg(AP, Lexical), ARG1(E) = va_arg(AP, Exp);      break;      case BinX:         OP(E) = va_arg(AP, Lexical), ARG1(E) = va_arg(AP, Exp),         ARG2(E) = va_arg(AP, Exp);      break;      case CondX:         ARG1(E) = va_arg(AP, Exp), ARG2(E) = va_arg(AP, Exp),         ARG3(E) = va_arg(AP, Exp);      break;   }   va_end(AP);   return EvalExp(E);}#define uO 0x10/* Operator types: 20 = ), 40 = :, 60 = ?, 80 = binary */#define bO 0x80int OpTab[] = { /* Bits 0-3: precedence, Bit 4:unary, Bits 5-7: operator type */   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0x20, 0x40, 0x60,   uO, uO, uO, uO, uO|bO|2, uO|bO|2, bO|1, bO|1, bO|1,   bO|4, bO|4, bO|4, bO|4, bO|5, bO|5, bO|9, bO|10,   bO|6, bO|7, bO|8, bO|3, bO|3, bO, bO,   0, 0, 0, 0, 0};char *Action[6] = {/*  .):?+ */   "...?+", /* BOT:     -> Exp $                 */   "B)B?+", /* PAR: Exp -> '(' Exp $ ')'         */   "AA:?+", /* COND Exp -> Exp '?' Exp $ ':' Exp */   "ccc?+", /* ELS: Exp -> Exp '?' Exp ':' Exp $ */   "bbbbC", /* BIN: Exp -> Exp bin Exp $         */   "uuuuu"  /* UN:  Exp -> un Exp $              */};Exp Parse(int Dir) {   Lexical L = OldL; Symbol ID; Exp A, B; int Act;   InExp = 1; Direct = Dir;   EP = EStack, OP = OStack, AP = AStack, TP = TStack;   PUSH(BOT);EXP:   switch (L) {      case LPAR: PUSH(PAR); L = Scan(); goto EXP;      case NUMBER: A = MakeExp(NumX, Value); L = Scan(); goto END_EX;      case DOLLAR:         A = MakeExp(AddrX, SegP, (word)LOC); L = Scan();      goto END_EX;      case SYMBOL: A = MakeExp(SymX, Sym); L = Scan(); goto END_EX;      default:         if ((OpTab[L]&uO)) { PUSH(UN); *OP++ = L; L = Scan(); goto EXP; }         ERROR("Expected an argument/prefix operator.");         A = MakeExp(NumX, 0);      goto END_EX;   }END_EX:   Act = Action[*--TP][OpTab[L] >> 5];   if (Act == 'C')      Act = ((OpTab[L]&0xe0) < (OpTab[OP[-1]]&0xe0))? '+': 'b';   switch (Act) {      case '+': TP++; PUSH(BIN); *OP++ = L; PutE(A); L = Scan(); goto EXP;      case '?': TP++; PUSH(COND); PutE(A); L = Scan(); goto EXP;      case ':': PUSH(ELS); PutE(A); L = Scan(); goto EXP;      case 'A': ERROR("Missing ':'"); PUSH(ELS); PutE(A); goto EXP;      case ')': L = Scan(); goto END_EX;      case 'B': ERROR("Missing ')'"); goto END_EX;      case 'u': A = MakeExp(UnX, *--OP, A); goto END_EX;      case 'b': A = MakeExp(BinX, *--OP, GetE(), A); goto END_EX;      case 'c': B = GetE(); A = MakeExp(CondX, GetE(), B, A); goto END_EX;      case '.': InExp = 0, Direct = 2; return A;   }}

⌨️ 快捷键说明

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