📄 assembler.cpp
字号:
if (strcmp(token, "iload") == 0) {
addCode(iloadC);
intparam = atoi(getToken(sourceFILE));
addInt16(intparam);
} else
if (strcmp(token, "istore") == 0) {
addCode(istoreC);
intparam = atoi(getToken(sourceFILE));
addInt16(intparam);
} else
if (strcmp(token, "dup") == 0) {
addCode(dupC);
} else
if (strcmp(token, "pop") == 0) {
addCode(popC);
} else
if (strcmp(token, "iconst_0") == 0) {
addCode(iconst_0C);
} else
if (strcmp(token, "iconst_1") == 0) {
addCode(iconst_1C);
} else
if (strcmp(token, "iconst_2") == 0) {
addCode(iconst_2C);
} else
if (strcmp(token, "iconst_3") == 0) {
addCode(iconst_3C);
} else
if (strcmp(token, "iconst_4") == 0) {
addCode(iconst_4C);
} else
if (strcmp(token, "iconst_5") == 0) {
addCode(iconst_5C);
} else
if (strcmp(token, "ldc_int") == 0) {
addCode(ldc_intC);
intparam = atoi(getToken(sourceFILE));
/* index to constant pool */
addIndex(getIntConstNr(intparam));
} else
if (strcmp(token, "ldc_string") == 0) {
addCode(ldc_stringC);
param = getStringToken(sourceFILE);
/* index to constant pool */
addIndex(getStrConstNr(param));
} else
if (strcmp(token, "call") == 0) {
addCode(callC);
param = getToken(sourceFILE);
/* index to constant pool */
addIndex(getStrConstNr(param));
} else
if (strcmp(token, "setint_mdl") == 0) {
addCode(setint_mdlC);
} else
if (strcmp(token, "setint_particle") == 0) {
addCode(setint_particleC);
} else
if (strcmp(token, "setint_ply") == 0) {
addCode(setint_plyC);
} else
if (strcmp(token, "setint_light") == 0) {
addCode(setint_lightC);
} else
if (strcmp(token, "setint_cam") == 0) {
addCode(setint_camC);
} else
if (strcmp(token, "sleep") == 0) {
addCode(sleepC);
} else
if (strcmp(token, "sleep_trig") == 0) {
addCode(sleep_trigC);
} else
if (strcmp(token, "cast_inttostring") == 0) {
addCode(cast_inttostringC);
} else
if (strcmp(token, "cast_stringtoint") == 0) {
addCode(cast_stringtointC);
} else
if (strcmp(token, "cast_booltostring") == 0) {
// This opcode is needed even if bools are represented by ints in the VM (can you think why?)
addCode(cast_booltostringC);
}
else {
printf("FATAL ERROR - unhandled opcode in assembler '%s'\n", token);
}
}
// Write the constant pool chunk to the output file.
void emitConstants() {
char id = CONSTANTS_ID;
CONSTANT *constantList = asmConstants;
char ctype;
int intval;
// write ID
fwrite(&id, 1, 1, emitFILE);
// write number of constants
fwrite(&nextconst, sizeof(unsigned int), 1, emitFILE);
// Loop over all constants
while (constantList) {
ctype = constantList->type;
fwrite(&ctype, 1, 1, emitFILE);
switch (ctype) {
case INT_CONST:
intval = constantList->val.intval;
fwrite(&intval, sizeof(int), 1, emitFILE);
break;
case ZSTRING_CONST:
writeZString(constantList->val.str, emitFILE);
break;
}
constantList = constantList->next;
}
}
// Write the code segment chunk to the file.
void emitCodeSegment() {
char id = CODE_ID;
/* write ID */
fwrite(&id, 1, 1, emitFILE);
/* write codesize */
fwrite(&codeposition, sizeof(unsigned int), 1, emitFILE);
/* write bytecode */
fwrite(bytecode, 1, codeposition, emitFILE);
}
/* ****************** ASSEMBLER ******************* */
void AssembleFile(char *fn)
{
char *token = NULL;
sourceFILE = fopen("emitted.a","r");
emitFILE = fopen(fn, "wb");
if (sourceFILE == NULL) {
printf("ERROR - Couldn't open source file 'emitted.a'\n");
return;
}
if (emitFILE == NULL) {
printf("ERROR - Couldn't open output file '%s'\n", fn);
return;
}
/* initialize the byte code buffer */
curCodeArraySize = START_SIZE;
bytecode = (unsigned char *)Malloc(START_SIZE);
token = getToken(sourceFILE);
while (token != NULL) {
// Which top-level token did we read?
if (strcmp(token, ".function") == 0)
AssembleFunction();
else
if (strcmp(token, ".program") == 0)
AssembleProgram();
else
reportError(line, "Illegal top-level token in assembly file");
/* Get next top-level */
token = getToken(sourceFILE);
}
/* fill in the plugs */
fillPlugs();
/* Now emit all constants and code */
emitConstants();
emitCodeSegment();
fclose(emitFILE);
fclose(sourceFILE);
}
// Assemble a function
void AssembleFunction() {
char id;
char *token;
char *tmp;
int end = 0;
// Create a new function header struct
FUNCTIONHEADER *header = NEW(FUNCTIONHEADER);
// The functions code will start here:
header->startCode = codeposition;
// First get name token and extract parameter info from it
token = getToken(sourceFILE);
tmp = token;
header->inputs = 0;
header->outputs = 0;
// Search for end of name.
while (*tmp != '(') {
end++;
tmp++;
}
// Count number of inputs to this function
while (*tmp != ')') {
tmp++;
header->inputs++;
}
header->inputs--; // We counted one too much in the above.
// Check if there is a return value from this function
tmp++;
if (*tmp != 'V') // Check if return type is non-VOID
header->outputs = 1;
// Zero-terminate token where the name ends.
token[end] = 0;
header->name = token;
// the prefix for our label lookup. The function name is unique
currentName = header->name;
// Now assemble the function
do {
token = getToken(sourceFILE);
if (isLabel(token)) {
token[strlen(token)-1] = 0;
setLabelPosition(token);
}
else
if (strcmp(token, ".limit_locals") == 0) {
token = getToken(sourceFILE);
header->localLimit = atoi(token);
}
else
if (strcmp(token, ".limit_stack") == 0) {
token = getToken(sourceFILE);
header->stackLimit = atoi(token);
}
else
if (strcmp(token, ".end_function") == 0) {
// Do nothing
}
else {
// If nothing else matches this must be a token from the functions code body.
asmCODE(token);
}
} while (token != NULL && (strcmp(token, ".end_function") != 0));
// This is where the code ends (points to the first byte code AFTER the function)
header->endCode = codeposition;
// Write function to the output file
id = FUNCTION_ID;
fwrite(&id, 1, 1, emitFILE); // Write a function chunk.
// write header
writeZString(header->name, emitFILE);
fwrite(&header->inputs, 1, 1, emitFILE);
fwrite(&header->outputs, 1, 1, emitFILE);
fwrite(&header->localLimit, 1, 1, emitFILE);
fwrite(&header->stackLimit, sizeof(unsigned short int), 1, emitFILE);
fwrite(&header->startCode, sizeof(unsigned int), 1, emitFILE);
fwrite(&header->endCode, sizeof(unsigned int), 1, emitFILE);
// Echo some of the info to the screen.
printf("func : '%s', inputs %i, outputs %i, codesize %i\n",
header->name, header->inputs, header->outputs, header->endCode - header->startCode );
}
// Pretty much the same as above. Look for the changes yourself
void AssembleProgram() {
char id;
char *token = NULL;
PROGRAMHEADER *header = NEW(PROGRAMHEADER);
header->startCode = codeposition;
header->triggerArgument = NULL;
// read name
header->name = getToken(sourceFILE);
// the prefix for our label lookup
currentName = header->name;
do {
token = getToken(sourceFILE);
if (isLabel(token)) {
token[strlen(token)-1] = 0;
setLabelPosition(token);
}
else
if (strcmp(token, ".limit_locals") == 0) {
token = getToken(sourceFILE);
header->localLimit = atoi(token);
}
else
if (strcmp(token, ".limit_stack") == 0) {
token = getToken(sourceFILE);
header->stackLimit = atoi(token);
}
else
if (strcmp(token, ".trigger_never") == 0) {
header->triggertype = trigger_neverK;
}
else
if (strcmp(token, ".trigger_on_init") == 0) {
header->triggertype = trigger_on_initK;
}
else
if (strcmp(token, ".trigger_on_click") == 0) {
header->triggertype = trigger_on_clickK;
token = getStringToken(sourceFILE);
header->triggerArgument = token;
}
else
if (strcmp(token, ".trigger_on_collide") == 0) {
header->triggertype = trigger_on_collideK;
token = getStringToken(sourceFILE);
header->triggerArgument = token;
}
else
if (strcmp(token, ".trigger_on_pickup") == 0) {
header->triggertype = trigger_on_pickupK;
token = getStringToken(sourceFILE);
header->triggerArgument = token;
}
else
if (strcmp(token, ".end_program") == 0) {
// Do nothing
}
else {
asmCODE(token);
}
} while (token != NULL && (strcmp(token, ".end_program") != 0));
header->endCode = codeposition;
// Write program
id = PROGRAM_ID;
fwrite(&id, 1, 1, emitFILE);
// write header
writeZString(header->name, emitFILE);
fwrite(&header->localLimit, 1, 1, emitFILE);
fwrite(&header->stackLimit, sizeof(unsigned short int), 1, emitFILE);
fwrite(&header->triggertype, 1, 1, emitFILE);
writeZString(header->triggerArgument, emitFILE);
fwrite(&header->startCode, sizeof(unsigned int), 1, emitFILE);
fwrite(&header->endCode, sizeof(unsigned int), 1, emitFILE);
// Echo to screen
printf("triggertype = %i, trigger Argument '%s'\n", header->triggertype, header->triggerArgument);
printf("prog : '%s' - codesize %i\n", header->name, header->endCode - header->startCode );
}
/* ***************************************************
** And we're done! That wasn't so hard was it?? **
** Congrats on completing your compiler! **
*************************************************** */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -