CPU0 的組譯器實作

開放電腦

簡介

函式庫

處理器

主機板

輸出入

虛擬機

組譯器

連結器

編譯器

嵌入式系統

作業系統

原始碼下載

文件下載

設計想法

訊息

相關網站

參考文獻

最新修改

簡體版

English

CPU0 的組譯器 (AS0) 之使用範例

C:\ccc\SP\code\ch12>as0 sum.asm0 sum.obj0
Assembler:asmFile=sum.asm0 objFile=sum.obj0
===============Assemble=============
        LD      R1, sum
        LD      R2, i
        LD      R3, ten
        LD      R4, one
FOR:    CMP     R2, R3
        JGT     EXIT
        ADD     R1, R2, R1
        ADD     R2, R4, R2
        JMP     FOR
EXIT:   RET
i:      RESW    1
sum:    WORD    0
ten:    WORD    10
one:    WORD    1
=================PASS1================
   0          LD   R1, sum        L  0 (null)
   4          LD   R2, i          L  0 (null)
   8          LD   R3, ten        L  0 (null)
   c          LD   R4, one        L  0 (null)
  10 FOR:     CMP  R2, R3         A 10 (null)
  14          JGT  EXIT           J 23 (null)
  18          ADD  R1, R2, R1     A 13 (null)
  1c          ADD  R2, R4, R2     A 13 (null)
  20          JMP  FOR            J 26 (null)
  24 EXIT:    RET                 J 2c (null)
  28 i:       RESW 1              D f0 (null)
  2c sum:     WORD 0              D f2 (null)
  30 ten:     WORD 10             D f2 (null)
  34 one:     WORD 1              D f2 (null)
===============SYMBOL TABLE=========
  24 EXIT:    RET                 J 2c (null)
  34 one:     WORD 1              D f2 (null)
  30 ten:     WORD 10             D f2 (null)
  2c sum:     WORD 0              D f2 (null)
  10 FOR:     CMP  R2, R3         A 10 (null)
  28 i:       RESW 1              D f0 (null)
=============PASS2==============
   0          LD   R1, sum        L  0 001f0028
   4          LD   R2, i          L  0 002f0020
   8          LD   R3, ten        L  0 003f0024
   c          LD   R4, one        L  0 004f0024
  10 FOR:     CMP  R2, R3         A 10 10230000
  14          JGT  EXIT           J 23 2300000c
  18          ADD  R1, R2, R1     A 13 13121000
  1c          ADD  R2, R4, R2     A 13 13242000
  20          JMP  FOR            J 26 26ffffec
  24 EXIT:    RET                 J 2c 2c000000
  28 i:       RESW 1              D f0 00000000
  2c sum:     WORD 0              D f2 00000000
  30 ten:     WORD 10             D f2 0000000a
  34 one:     WORD 1              D f2 00000001
==========Save to ObjFile:sum.obj0==========
001f0028002f0020003f0024004f0024102300002300000c131210001324200026ffffec2c000000
00000000000000000000000a00000001

CPU0 組譯器的原始碼

引用檔:Assembler.h

#ifndef ASSEMBLER_H
#define ASSEMBLER_H

#include "Cpu0.h"

typedef struct {
  Array *codes;
  HashTable *symTable;
  HashTable *opTable;
} Assembler;

typedef struct {
  int address, opCode, size;
  char *label, *op, *args, type;
  char *objCode;
} AsmCode;

void assemble(char *asmFile, char *objFile); // 組譯器的主要函數 

Assembler* AsmNew();
void AsmFree(Assembler *a);

void AsmPass1(Assembler *a, char *text);
void AsmPass2(Assembler *a);
void AsmSaveObjFile(Assembler *a, char *objFile);
void AsmTranslateCode(Assembler *a, AsmCode *code);

AsmCode* AsmCodeNew(char *line);
void AsmCodeFree(AsmCode *code);
int AsmCodePrintln(AsmCode *code);

#endif

原始程式:Assembler.c

#include "Assembler.h"

void assemble(char *asmFile, char *objFile) {
  printf("Assembler:asmFile=%s objFile=%s\n",asmFile,objFile);
  printf("===============Assemble=============\n");
  char *text = newFileStr(asmFile);
  Assembler *a = AsmNew();
  AsmPass1(a, text);
  printf("===============SYMBOL TABLE=========\n");  
  HashTableEach(a->symTable, (FuncPtr1) AsmCodePrintln);
  AsmPass2(a);
  AsmSaveObjFile(a, objFile);
  AsmFree(a); 
  freeMemory(text);
}

Assembler* AsmNew() {
  Assembler *a=ObjNew(Assembler, 1);
  a->codes = ArrayNew(10);
  a->symTable = HashTableNew(127);
  a->opTable = OpTableNew();
  return a;
}

void AsmFree(Assembler *a) {
  ArrayFree(a->codes, (FuncPtr1) AsmCodeFree);
  HashTableFree(a->symTable);
  OpTableFree();
  ObjFree(a);
}

void AsmPass1(Assembler *a, char *text) {
  int i, address = 0, number;
  Array* lines = split(text, "\r\n", REMOVE_SPLITER);
  ArrayEach(lines, strPrintln);
  printf("=================PASS1================\n");
  for (i=0; i<lines->count; i++) {
      strReplace(lines->item[i], SPACE, ' ');
      AsmCode *code = AsmCodeNew(lines->item[i]);
      code->address = address;
      Op *op = HashTableGet(opTable, code->op);
      if (op != NULL) {
        code->opCode = op->code;
        code->type = op->type;
      }
      if (strlen(code->label)>0)
        HashTablePut(a->symTable, code->label, code);
      ArrayAdd(a->codes, code);
      AsmCodePrintln(code);
      code->size = AsmCodeSize(code);
      address += code->size;
  }
  ArrayFree(lines, strFree);
}

void AsmPass2(Assembler *a) {
  printf("=============PASS2==============\n");
  int i;
  for (i=0; i<a->codes->count; i++) {
    AsmCode *code = a->codes->item[i];
    AsmTranslateCode(a, code);
    AsmCodePrintln(code);
  }
}

void AsmTranslateCode(Assembler *a, AsmCode *code) {
  char p1[100], p2[100], p3[100], pt[100];
  int ra=0, rb=0, rc=0, cx=0;
  char cxCode[9]="00000000", objCode[100]="", args[100]="";
  strcpy(args, code->args);
  strReplace(args, ",", ' ');
  int pc = code->address + 4;
  switch (code->type) {
    case 'J' :
      if (!strEqual(args, "")) {
        AsmCode *labelCode = HashTableGet(a->symTable,args);
        cx = labelCode->address - pc;
        sprintf(cxCode, "%8x", cx);
      }
      sprintf(objCode, "%2x%s", code->opCode, &cxCode[2]);
      break;
    case 'L' :
      sscanf(args, "R%d %s", &ra, p2);
      if (strHead(p2, "[")) {
        sscanf(p2, "[R%d+%s]", &rb, pt);
        if (sscanf(pt, "R%d", &rc)<=0)
          sscanf(pt, "%d", &cx);
      } else if (sscanf(p2, "%d", &cx)>0) {
      } else {
        AsmCode *labelCode = HashTableGet(a->symTable, p2);
        cx = labelCode->address - pc;
        rb = 15; // R[15] is PC
      }
      sprintf(cxCode, "%8x", cx);
      sprintf(objCode, "%2x%x%x%s", code->opCode, ra, rb, &cxCode[4]);
      break;
    case 'A' : 
      sscanf(args, "%s %s %s", p1, p2, p3);
      sscanf(p1, "R%d", &ra);
      sscanf(p2, "R%d", &rb);
      if (sscanf(p3, "R%d", &rc)<=0)
        sscanf(p3, "%d", &cx);
      sprintf(cxCode, "%8x", cx);
      sprintf(objCode, "%2x%x%x%x%s", code->opCode,ra,rb,rc,&cxCode[5]);
      break;
    case 'D' : {
      char format4[]="%8x", format1[]="%2x", *format = format1;
      switch (code->opCode) {
        case OP_RESW:
        case OP_RESB:
          memset(objCode, '0', code->size*2);
          objCode[code->size*2] = '\0';
          break;
        case OP_WORD:
          format = format4;
        case OP_BYTE: {
          Array *array = split(args, " ", REMOVE_SPLITER);
          char *objPtr = objCode;
          int i=0;
          for (i=0; i<array->count; i++) {
              char *item = array->item[i];
              if (isdigit(item[0]))
                sprintf(objPtr, format, atoi(item));
              else {
                AsmCode *itemCode = HashTableGet(a->symTable, item);
                sprintf(objPtr, format, itemCode->address);
              }
              objPtr += strlen(objPtr);
          }
          ArrayFree(array, strFree);
          break;
        } // case OP_BYTE:
      } // switch
      break;
    } // case 'D'
    default: 
      strcpy(objCode, "");
      break;
  }
  strReplace(objCode, " ", '0');
  code->objCode = newStr(objCode);
}

void AsmSaveObjFile(Assembler *a, char *objFile) {
  printf("==========Save to ObjFile:%s==========\n", objFile);
  FILE *file = fopen(objFile, "wb");
  int i;
  for (i=0; i<a->codes->count; i++) {
    AsmCode *code = a->codes->item[i];
    char *objPtr = code->objCode;
    while (*objPtr != '\0') {
      int x;
      sscanf(objPtr, "%2x", &x);
      assert(x >= 0 && x < 256);
      BYTE b = (BYTE) x;
      fwrite(&b, sizeof(BYTE), 1, file);
      objPtr += 2;
      char bstr[3];
      sprintf(bstr, "%2x", b);
      strReplace(bstr, " ", '0');
      printf("%s", bstr);
    }
  }
  printf("\n");
  fclose(file);
}

int AsmCodePrintln(AsmCode *code) {
  char label[100] = "";
  if (strlen(code->label)>0)
    sprintf(label, "%s:", code->label);
  printf("%4x %-8s %-4s %-14s %c %2x %s\n", code->address, label, 
           code->op, code->args, code->type, 
           code->opCode, code->objCode);
}

AsmCode* AsmCodeNew(char *line) {
  AsmCode* code = ObjNew(AsmCode,1);
  char label[100]="", op[100]="", args[100]="", temp[100];
  int count = sscanf(line, "%s %s %[^;]", label, op, args);
  if (strTail(label, ":")) {
    strTrim(temp, label, ":");
    strcpy(label, temp);
  } else {
    strcpy(label, "");
    sscanf(line, "%s %[^;]", op, args);
  }
//  printf("label=%s op=%s args=%s\n", code->label, op, args);
  code->label = newStr(label);
  code->op = newStr(op);
  strTrim(temp, args, SPACE);
  code->args = newStr(temp);
  code->type = ' ';
  code->opCode = OP_NULL;
//  AsmCodePrintln(code);
  return code;
}

void AsmCodeFree(AsmCode *code) {
  freeMemory(code->label);
  freeMemory(code->op);
  freeMemory(code->args);
  freeMemory(code->objCode);
  freeMemory(code);
}

int AsmCodeSize(AsmCode *code) {
  int number;
  switch (code->opCode) {
    case OP_RESW : 
      return 4 * atoi(code->args);
    case OP_RESB : 
      return atoi(code->args);
    case OP_WORD : 
      number = atoi(code->args);
      return 4 * (strCountChar(code->args, ",")+1);
    case OP_BYTE : 
      number = atoi(code->args);
      return strCountChar(code->args, ",")+1;
    case OP_NULL :
      return 0;
    default :
      return 4;
  }
}

Facebook

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License