📄 code.cpp
字号:
emitCode("ADD EAX,EBX");
break;
case MINUS:
emitCode("SUB EAX,EBX");
break;
case MUL:
emitCode("IMUL EBX");
break;
case DIV:
emitCode("CDQ");
emitCode("IDIV EBX");
break;
}
emitTemp(tempR);
break;
case RELOP:
label = emitLabel();
label2 = emitLabel();
genCodePart(t->pChild[0], STACK); //oprand1 save to stack
genCodePart(t->pChild[1], EBX); //oprand2 save to ac1
emitCode("POP EAX"); //get oprand1
emitCode("SUB EAX,EBX"); //do the comparation
switch(t->tokenT)
{
case LT:
emitOneOprand("JL",label);
break;
case LTEQ:
emitOneOprand("JLE",label);
break;
case GT:
emitOneOprand("JG",label);
break;
case GTEQ:
emitOneOprand("JGE",label);
break;
case EQ:
emitOneOprand("JE",label);
break;
case NEQ:
emitOneOprand("JNE",label);
break;
}
emitCode("MOV EAX,0");
emitOneOprand("JMP", label2);
emitLine(label+':');
emitCode("MOV EAX,1"); //if true, jump here
emitLine(label2+':');
//At this time
//EAX=1 represents true, 0 represents false
emitTemp(tempR);
break;
case STMT:
label=emitLabel();
switch(t->childkind.stmtK)
{
case IF_STMT:
label2=emitLabel();
emitComment("If statement start");
genCodePart(t->pChild[0], EAX); //condition expression
emitCode("CMP EAX,0");
emitOneOprand("JE", label); //jump to else when false
genCodePart(t->pChild[1], NONE);
emitOneOprand("JMP", label2); //jump to end
emitLine(label+':');
genCodePart(t->pChild[2], NONE);
emitLine(label2+':');
emitComment("If statement end");
break;
case WHILE_STMT:
label2=emitLabel();
emitLine(label2+':');
emitComment("While statement start");
genCodePart(t->pChild[0], EAX); //condition expression
emitCode("CMP EAX,0");
emitOneOprand("JE", label); //jump out
genCodePart(t->pChild[1], NONE);
emitOneOprand("JMP", label2); //jump back for loop
emitLine(label+':');
emitComment("While statement end");
break;
case RETURN_STMT:
emitComment("Return statement start");
genCodePart(t->pChild[0], EAX);
emitCode("MOV SP,BP");
emitCode("POP BP"); //fp=ofp
emitNoOprand("RET"); //return
emitComment("Return statement end");
break;
}
break;
case REFER:
emitComment(string("Reference of ")+t->name);
s=st_lookup(t->name);
i=s->nestlevel;
genCodePart(t->pChild[0], EBX); //subsript
//Ugly code here:(, once we find a arrayname without
//any subcript, we need its address rather than its
//value, so temporarily change the symbol attribute...
if(s->symboltype==ARRAY_SYMBOL
&& t->pChild[0]==NULL)
{
s->symboltype = VAR_SYMBOL;
emitRefer(s, 1);
s->symboltype = ARRAY_SYMBOL;
}
else if(s->symboltype==ARRAYADDR_SYMBOL &&
t->pChild[0]==NULL)
{
s->symboltype = VAR_SYMBOL;
emitRefer(s, 0);
s->symboltype = ARRAYADDR_SYMBOL;
}
else
emitRefer(s, 0);
emitTemp(tempR);
break;
case CALL:
emitComment(string("Call ")+t->name);
//Reverse the argument order first
//We'd like to push the args in
//reverse order
s=st_lookup(t->name);
ttemp=t->pChild[0];
while(ttemp!=NULL){
if(ttemp->pNext==NULL)
break;
ttemp=ttemp->pNext;
}
t->pChild[0]=ttemp;
while(ttemp!=NULL)
{
ttemp->pNext=ttemp->pPrev;
ttemp=ttemp->pPrev;
}
//Just pass the head of the arg-list
//left ones will be dealt by genCodePart(t->pNext,tempR)
genCodePart(t->pChild[0], STACK);
emitOneOprand("CALL", '_'+t->name);
if(s->paramAlloc > 0){ // eliminates all paramters
os<<s->paramAlloc;
emitTwoOprand("ADD", regs[SP], os.str());
os.str()="";
}
emitTemp(tempR);
break;
case EXP:
switch(t->childkind.expK)
{
case ASSIGN_EXP:
emitComment("Assignment start: "+t->name);
s=st_lookup(t->name);
genCodePart(t->pChild[1], ECX); //value to assign=>ECX
genCodePart(t->pChild[0], EBX); //subscript=>EBX
emitRefer(s, 1); //the address to EAX
emitCode("MOV [EAX],ECX"); //do the assignment
emitCode("MOV EAX,ECX"); //the value of this assignment-exp
emitTemp(tempR);
break;
}
break;
case NUM:
emitComment("Literal number: "+t->name);
emitTwoOprand("MOV", regs[EAX],
t->name);
emitTemp(tempR);
break;
}
genCodePart(t->pNext,tempR);
}
}
// Generate the global data declarations
void genDataPart(TreeNode *t)
{
TreeNode *ttemp;
emitLine("_DATA_SEG SEGMENT PUBLIC");
while(t!=NULL){
// Continuous variable declaration
if(t->kind==DECLAR&&t->childkind.declarK==VAR_DECLAR_LIST){
ttemp = t->pChild[0];
while(ttemp!=NULL) {
switch(ttemp->childkind.declarK){
case VAR_DECLAR:
emitDeclare(ttemp->name, 1);
break;
case ARRAY_DECLAR:
emitDeclare(ttemp->name, ttemp->arraynum);
break;
}
ttemp = ttemp->pNext;
}
}
t = t->pNext;
}
emitLine("_DATA_SEG ENDS");
}
// Generate the initialization code for global data declarations
//
// And no worry about regeneration when call genCodePart with
// the whole grammar tree later, I've delt with it
void genGlobalInitPart(TreeNode *t)
{
TreeNode *ttemp;
emitComment("Global initialization starts");
while(t!=NULL){
if(t->kind==DECLAR){
switch(t->childkind.declarK){
case VAR_DECLAR_LIST:
ttemp = t->pChild[0];
while(ttemp!=NULL) {
genCodePart(ttemp->pChild[0], NONE);
ttemp->pChild[0] = NULL; //Avoid code regeneration
ttemp = ttemp->pNext;
}
break;
}
}
t = t->pNext;
}
emitComment("Global initialization ends");
}
// Find function declarations without definition
// And generate 'EXTRN' declaration for them
void genExternSymbol()
{
int i, n=0;
string externDeclare="EXTRN ";
for(i=0;i<BUCKET_SIZE;i++) {
SymbolRecord *sr = GlobalBucket.pRecord[i];
while(sr!=NULL) {
// No definition?
if(sr->symboltype==FUNC_DECLAR_SYMBOL) {
externDeclare+='_';
externDeclare+=sr->name;
externDeclare+=":NEAR,";
n++;
}
sr = sr->pNext;
}
}
if(n>0) {
externDeclare.at(externDeclare.length()-1)=' ';
emitLine(externDeclare);
}
}
void genCode(TreeNode *t)
{
/* This check can be ignored, for the link of assembler
will check this out:)
SymbolRecord *s=st_lookup(string("main"));
if(s==NULL)
GenError("Entrypoint 'main' not found");
*/
emitLine(".386");
genDataPart(t);
emitLine("_CODE_SEG SEGMENT USE16 PUBLIC");
emitLine("ASSUME CS:_CODE_SEG,DS:_DATA_SEG");
genExternSymbol();
emitLine("START:");
emitTwoOprand("XOR", "EBP", "EBP");
emitTwoOprand("MOV", "AX", "_DATA_SEG");
emitTwoOprand("MOV", regs[DS], "AX");
emitTwoOprand("MOV", regs[ES], "AX");
genGlobalInitPart(t);
emitOneOprand("CALL", "_main");
emitTwoOprand("MOV", "AX", "4C00H"); //Terminate the program
emitOneOprand("INT","21H");
genCodePart(t, NONE);
emitLine("_CODE_SEG ENDS");
emitLine("END START"); //Entry point
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -