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

📄 link.c

📁 一个C style Assembler的source code
💻 C
字号:
#include <stdlib.h>#include <stdio.h>#include "io.h"#include "ex.h"#include "res.h"#include "st.h"typedef struct FileBuf *FileBuf;struct FileBuf {   char *Name;   long Loc, Files, Segs, Gaps, Syms, Exps, Relocs;   char **File; Segment Seg; Gap G; Symbol *Sym;};FileBuf FTab; int Fs;typedef struct Block *Block;struct Block {   char *Src, *Obj; Segment Seg; Block Next;};static Block *BHead;static int *BSize;static Segment USeg;typedef struct Image *Image;struct Image {   word Base; long Size; char *Src, *Obj; word Line; long Loc;   Image Prev, Next;};static Image IHead, ITail;Exp *ExpBuf;static Image FormImage(   word Base, long Size, char *Src, char *Obj, word Line, long Loc) {   Image IP = (Image)Allocate(sizeof *IHead);   IP->Base = Base, IP->Size = Size, IP->Src = Src, IP->Obj = Obj,   IP->Line = Line, IP->Loc = Loc;   return IP;}static void SetImage(void) {   Block BP;   for (IHead = ITail = 0, BP = BHead[0]; BP != 0; BP = BP->Next) {      Segment Seg = BP->Seg; Image P, IP, NewI;      for (IP = IHead; IP != 0; IP = IP->Next)         if (IP->Base >= Seg->Base) break;      P = (IP == 0)? ITail: IP->Prev;      if (P != 0 && P->Base + P->Size > Seg->Base)         FATAL("Overlapping segments at [%d] %s and [%d] %s.",            P->Line, P->Src, Seg->Line, BP->Src         );      if (IP != 0 && Seg->Base + Seg->Size > IP->Base)         FATAL("Overlapping segments at [%d] %s and [%d] %s.",            Seg->Line, BP->Src, IP->Line, IP->Src         );      NewI = FormImage(         Seg->Base, Seg->Size, BP->Src, BP->Obj, Seg->Line, Seg->Loc      );      if (P == 0) IHead = NewI; else P->Next = NewI;      if (IP == 0) ITail = NewI; else IP->Prev = NewI;      NewI->Next = IP, NewI->Prev = P;   }}static void FitGap(Gap G) {   Image P, IP, NewI; long End, EndP;   word Base = G->Seg->Base + G->Offset; long Size = G->Size;   for (IP = IHead; IP != 0; IP = IP->Next)      if (IP->Base > Base) break;   P = (IP == 0)? ITail: IP->Prev;   if (P == 0) FATAL("Internal error (2).");   End = Base + Size, EndP = P->Base + P->Size;   if (EndP < End) FATAL("Internal error (3).");   if (P->Base < Base) {      P->Size = Base - P->Base;      if (EndP > End) {         NewI = FormImage(            (word)End, EndP - End, P->Src, P->Obj, P->Line, P->Loc + P->Size         );         NewI->Next = IP, P->Next = NewI;         NewI->Prev = P;         if (IP == 0) ITail = NewI; else IP->Prev = NewI;      }   } else if (EndP > End) P->Base += Size, P->Size -= Size;   else {      if (P->Prev == 0) IHead = P->Next; else P->Prev->Next = P->Next;      if (P->Next == 0) ITail = P->Prev; else P->Next->Prev = P->Prev;      free(P);   }}typedef struct Free *Free;struct Free {   word Base; long Size; Block BP;};static Free *FHead;static int *FSize;void SetFree(void) {   int T;   FHead = (Free *)Allocate(SEG_TYPES * sizeof *FHead);   FSize = (int *)Allocate(SEG_TYPES * sizeof *FSize);   for (T = 0; T < SEG_TYPES; T++) {      Block P, B; Free F; long Base;      FHead[T] = (Free)Allocate((BSize[T] + 1) * sizeof *FHead[T]);      for (P = 0, B = BHead[T], F = FHead[T]; B != 0; P = B, B = B->Next) {         Base = (P == 0)? AddrTab[T].Lo: (long) P->Seg->Base + P->Seg->Size;         if (Base >= B->Seg->Base) continue;         F->Base = Base, F->Size = (long)B->Seg->Base - Base, F->BP = P, F++;      }      Base = (P == 0)? AddrTab[T].Lo: (long) P->Seg->Base + P->Seg->Size;      if (Base <= AddrTab[T].Hi)         F->Base = Base, F->Size = (long)AddrTab[T].Hi + 1 - Base,         F->BP = P, F++;      FSize[T] = F - FHead[T];   }}void PurgeFree(void) {   int T;   for (T = 0; T < SEG_TYPES; T++) free(FHead[T]);   free(FHead), free(FSize);}void BestFit(char *Obj, Segment Seg) {   byte T = Seg->Type; Free Best, FP; Block B;   if (!Seg->Rel) return;   StartLine = Seg->Line, StartF = Seg->File;   for (Best = 0, FP = FHead[T]; FP < FHead[T] + FSize[T]; FP++) {      if (         Seg->Size <= FP->Size && (Best == 0 || FP->Size < Best->Size)      ) Best = FP;   }   if (Best == 0) FATAL("Cannot fit segment.");   B = (Block)Allocate(sizeof *B);   B->Seg = Seg, B->Src = FileTab[StartF], B->Obj = Obj;   if (Best->BP == 0)      B->Next = BHead[T], BHead[T] = B;   else      B->Next = Best->BP->Next, Best->BP->Next = B;   Seg->Rel = 0, Seg->Base = Best->Base,   Best->BP = B, Best->Base += Seg->Size, Best->Size -= Seg->Size;}void FitSegs(FileBuf F) {   int S; Segment Seg;   FileTab = F->File;   for (S = TYPES; S < F->Segs; S++) {      Seg = F->Seg + S - TYPES, BestFit(F->Name, Seg);   }}void SetSeg(void) {   Segment S; int I;   USeg = (Segment)Allocate(TYPES * sizeof *USeg);   for (S = USeg; S < USeg + TYPES; S++)      S->Line = S->File = 0, S->Rel = 0, S->Type = S - USeg,      S->Base = 0, S->Size = 0, S->Loc = 0L;   BHead = (Block *)Allocate(SEG_TYPES * sizeof *BHead);   BSize = (int *)Allocate(SEG_TYPES * sizeof *BSize);   for (I = 0; I < SEG_TYPES; I++) BHead[I] = 0, BSize[I] = 0;}void FreeBlocks(void) {   int I;   for (I = 0; I < SEG_TYPES; I++) {      Block B, N;      for (B = BHead[I]; B != 0; B = N) N = B->Next, free(B);   }   free(BHead), free(BSize);}void Fit(char *Obj, Segment Seg) {   byte T = Seg->Type; Block Cur, Prev, B;   if (Seg->Rel) return;   for (Prev = 0, Cur = BHead[T]; Cur != 0; Prev = Cur, Cur = Cur->Next)      if (Cur->Seg->Base >= Seg->Base) break;   if (Prev != 0 && Prev->Seg->Base + Prev->Seg->Size > Seg->Base)      ERROR("Overlapping segments: %s [%d] and %s [%d].",         FileTab[Seg->File], Seg->Line, Prev->Src, Prev->Seg->Line      );   if (Cur != 0 && Cur->Seg->Base < Seg->Base + Seg->Size)      ERROR("Overlapping segments: %s [%d] and %s [%d].",         FileTab[Seg->File], Seg->Line, Cur->Src, Cur->Seg->Line      );   B = (Block)Allocate(sizeof *B);   B->Src = FileTab[Seg->File], B->Obj = Obj, B->Seg = Seg, B->Next = Cur;   if (Prev == 0) BHead[T] = B; else Prev->Next = B;   BSize[T]++;}void GetHead(FileBuf F) {   word MAGIC; long S; byte Buf[0x100];   FILE *FP = fopen(F->Name, "rb+");   if (FP == 0) FATAL("Cannot open %s.", F->Name);   MAGIC = GetW(FP);   if (MAGIC != 0x55aa) FATAL("Invalid object file %s.", F->Name);   F->Loc = GetL(FP),   F->Files = GetL(FP), F->Segs = GetL(FP),   F->Gaps = GetL(FP), F->Syms = GetL(FP),   F->Exps = GetL(FP), F->Relocs = GetL(FP);   S = F->Loc + F->Files + F->Segs + F->Gaps + F->Syms + F->Exps + F->Relocs;   if (GetL(FP) != S&0xffffffff) FATAL("Corrupt object file %s.", F->Name);   F->File = (char **)Allocate((word)F->Files * sizeof *F->File);   F->Seg = (F->Segs < TYPES)? 0: (Segment)Allocate((word)(F->Segs - TYPES) * sizeof *F->Seg);   F->G = (Gap)Allocate((word)F->Gaps * sizeof *F->G);   F->Sym = (Symbol *)Allocate((word)F->Syms * sizeof *F->Sym);   FileTab = F->File;   fseek(FP, F->Loc, SEEK_SET);   for (S = 0; S < F->Files; S++) {      word L;      L = GetW(FP), fread(Buf, 1, L, FP), Buf[L] = '\0';      F->File[S] = CopyS(Buf);   }   for (S = TYPES; S < F->Segs; S++) {      Segment Seg = F->Seg + S - TYPES; word U;      Seg->Line = GetW(FP), Seg->File = GetW(FP),      U = GetW(FP), Seg->Size = GetW(FP),      Seg->Base = GetW(FP), Seg->Loc = GetL(FP);      Seg->Rel = (U >> 8)&1, Seg->Type = U&0xff;      Fit(F->Name, Seg);   }   for (S = 0; S < F->Gaps; S++) {      Gap G = F->G + S; word Sg;      Sg = GetW(FP), G->Offset = GetW(FP), G->Size = GetW(FP);      G->Seg = Sg < TYPES? &USeg[Sg]: &F->Seg[Sg - TYPES];   }   for (S = 0; S < F->Syms; S++) {      Symbol Sym; byte B, Defined, Global, Address; word U, L, Offset;      B = GetB(FP), U = GetW(FP), Offset = GetW(FP),      L = GetW(FP);      if (L > 0) fread(Buf, 1, L, FP);      Buf[L] = '\0';      Global = (B&8)? 1: 0, Defined = (B&4)? 1: 0, Address = (B&2)? 1: 0;      if (!Global) {         Sym = (Symbol)Allocate(sizeof *Sym);         Sym->Variable = 0, Sym->Address = Address;         Sym->Global = Global, Sym->Defined = Defined;         Sym->Seg = !Address? 0: U < TYPES? &USeg[U]: &F->Seg[U - TYPES];         Sym->Offset = Offset;         Sym->Index = F - FTab;         Sym->Name = CopyS(Buf);      } else {         Sym = LookUp(Buf);         if (Sym->Defined && Defined)            ERROR("Symbol %s redefined: %s %s.",               Sym->Name, FTab[Sym->Index].Name, F->Name            );         else {            if (Sym->Address) {               Segment Seg = U < TYPES? &USeg[U]: &F->Seg[U - TYPES];               if (!Address)                  ERROR("Address %s redeclared as number: %s %s",                     Sym->Name, FTab[Sym->Index].Name, F->Name                  );               else if (Sym->Seg->Type != Seg->Type)                  ERROR("Type mismatch %s: %s %s",                     Sym->Name, FTab[Sym->Index].Name, F->Name                  );            } else if (Address && Sym->Global)               ERROR("Number %s redeclared as address: %s %s",                  Sym->Name, FTab[Sym->Index].Name, F->Name               );            if (Defined || !Sym->Global) {               Sym->Variable = 0, Sym->Address = Address;               Sym->Global = Global, Sym->Defined = Defined;               Sym->Seg = !Address? 0: U < TYPES? &USeg[U]: &F->Seg[U - TYPES],               Sym->Offset = Offset;               Sym->Index = F - FTab;            }         }      }      F->Sym[S] = Sym;   }   F->Loc = ftell(FP);   fclose(FP);}typedef struct RList *RList;struct RList {   byte Size; long PC, Val; RList Next;};RList RHead;void AddReloc(byte Size, long PC, long Val) {   RList R = Allocate(sizeof *R), P, S;   for (P = 0, S = RHead; S != 0; P = S, S = S->Next)      if (S->PC >= PC) break;   if (S != 0 && S->PC == PC) FATAL("Internal error (4).");    if (P == 0) RHead = R; else P->Next = R;   R->Next = S,   R->Size = Size, R->PC = PC, R->Val = Val;}void SetRelocs(FileBuf F) {   long S; struct Item IBuf; Exp E, NextE;   FILE *FP = fopen(F->Name, "rb+");   if (FP == 0) FATAL("Cannot open %s.", F->Name);   FileTab = F->File; fseek(FP, F->Loc, SEEK_SET);   ExpBuf = (Exp *)Allocate((unsigned)F->Exps * sizeof *ExpBuf);   ExpInit();   for (S = 0; S < F->Exps; S++) {      Exp *EP = ExpBuf + S; byte Tag; Segment Seg; Exp A, B, C;      word Line, File, U, Offset; byte Op;      StartLine = GetW(FP), StartF = GetW(FP), Tag = GetB(FP);      switch (Tag) {         case NumX:            Value = GetW(FP); *EP = MakeExp(NumX, Value);         break;         case AddrX:            U = GetW(FP), Offset = GetW(FP);            Seg = U < TYPES? &USeg[U]: &F->Seg[U - TYPES];            *EP = MakeExp(AddrX, Seg, Offset);         break;         case SymX:            U = GetW(FP); *EP = MakeExp(SymX, F->Sym[U]);         break;         case UnX:            Op = GetB(FP),            U = GetW(FP), A = ExpBuf[U],            *EP = MakeExp(UnX, Op, A);         break;         case BinX:            Op = GetB(FP),            U = GetW(FP), A = ExpBuf[U],            U = GetW(FP), B = ExpBuf[U],            *EP = MakeExp(BinX, Op, A, B);         break;         case CondX:            U = GetW(FP), A = ExpBuf[U],            U = GetW(FP), B = ExpBuf[U],            U = GetW(FP), C = ExpBuf[U],            *EP = MakeExp(CondX, A, B, C);         break;      }   }   for (S = 0; S < F->Relocs; S++) {      word U, PC;      IBuf.Line = GetW(FP), IBuf.File = GetW(FP),      IBuf.Tag = GetB(FP),      U = GetW(FP), IBuf.E = ExpBuf[U],      U = GetW(FP), IBuf.Seg = U < TYPES? &USeg[U]: &F->Seg[U - TYPES];      IBuf.Offset = GetW(FP);      Resolve(&IBuf);      PC = (long)IBuf.Seg->Base + (long)IBuf.Offset;      switch (IBuf.Tag) {         case 'b': AddReloc(1, PC, LVal); break;         case 'w': AddReloc(2, PC, LVal); break;         default: FATAL("Internal error (5).");      }   }   fclose(FP);   for (E = ExpHead; E != 0; E = NextE) NextE = E->Next, free(E);   free(ExpBuf);}/* HEX OUTPUT ROUTINES */FILE *OutF = 0;byte HexBuf[0x10]; int HexX;long HexAddr;void OpenHex(char *Hex) {   OutF = fopen(Hex, "w");   if (OutF == 0) FATAL("Cannot open output file.");   HexX = 0;}void EndHex(void) {   if (HexX > 0) {      int H, Sum;      Sum = (HexAddr&0xff) + ((HexAddr >> 8)&0xff) + HexX;      fprintf(OutF, ":%02X%04X00", HexX, HexAddr);      for (H = 0; H < HexX; H++)         fprintf(OutF, "%02X", HexBuf[H]), Sum += HexBuf[H];      fprintf(OutF, "%02X\n", (-Sum)&0xff);      HexX = 0;   }}void PutHex(long Addr, byte Hex) {   if (HexX == 0) HexAddr = Addr;   HexBuf[HexX++] = Hex;   if (HexX == 0x10) {      int H, Sum;      Sum = (HexAddr&0xff) + ((HexAddr >> 8)&0xff) + HexX;      fprintf(OutF, ":10%04X00", HexAddr);      for (H = 0; H < HexX; H++)         fprintf(OutF, "%02X", HexBuf[H]), Sum += HexBuf[H];      fprintf(OutF, "%02X\n", (-Sum)&0xff);      HexX = 0;   }}void CloseHex(void) {   EndHex();   fprintf(OutF, ":00000001FF\n");   fclose(OutF);}void GenImage(char *Hex) {   Image IP; RList R; FILE *FP; char *File;   FP = 0, File = 0;   OpenHex(Hex);   for (IP = IHead, R = RHead; IP != 0; IP = IP->Next) {      long Addr;      if (IP->Obj != File) {         if (FP != 0) fclose(FP), FP = 0;         FP = fopen(IP->Obj, "rb+");         if (FP == 0) FATAL("Cannot open %s.", IP->Obj);      }      fseek(FP, IP->Loc, SEEK_SET);      for (Addr = IP->Base; Addr < IP->Base + IP->Size; ) {         if (R != 0 && R->PC < Addr) FATAL("Internal error (6).");         if (R != 0 && R->PC == Addr) {            switch (R->Size) {               case 1: fgetc(FP); PutHex(Addr++, (byte)(R->Val&0xff)); break;               case 2:                  fgetc(FP), fgetc(FP);                  PutHex(Addr++, (byte)((R->Val >> 8)&0xff)),                  PutHex(Addr++, (byte)(R->Val&0xff));               break;               default: FATAL("Internal error (7).");            }            R = R->Next;         } else {            int Ch = fgetc(FP);            if (Ch == EOF) FATAL("Internal error (8).");            PutHex(Addr++, (byte)(Ch&0xff));         }      }      if (IP->Next != 0 && IP->Base + IP->Size < IP->Next->Base) EndHex();   }   CloseHex();}void Link(char *Hex) {   int A;   Active = 1, Phase = 2;   SymInit(); SetSeg();   for (A = 0; A < Fs; A++) GetHead(FTab + A);   for (Sym = NIL->Next[0]; Sym != NIL; Sym = Sym->Next[0])      if (!Sym->Defined) ERROR("Unresolved external: %s.", Sym->Name);   CHECK();   InSeg = 1;   SetFree();   for (A = 0; A < Fs; A++) FitSegs(FTab + A);   PurgeFree();   InSeg = 0;   CHECK();   SetImage();   for (A = 0; A < Fs; A++) {      Gap G; FileBuf F = FTab + A;      for (G = F->G; G < F->G + F->Gaps; G++) FitGap(G);   }   CHECK();   FreeBlocks();   InSeg = 1; RHead = 0;   for (A = 0; A < Fs; A++) SetRelocs(FTab + A);   InSeg = 0;   CHECK();   GenImage(Hex);}

⌨️ 快捷键说明

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