訊息
|
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
|
Post preview:
Close preview