📄 c2asm.cpp
字号:
}
void t(expr &p)
{
if(input.clas=="parenthesis_open" || input.clas=="id" || input.clas=="int_const" ||
input.clas=="long_const" )
{
expr p1;
u(p1);
add(p1,p);
}
else reject();
}
void add(expr p,expr &q)
{
if(input.clas=="add_sub"
&& input.index==15)
{
advanc();
expr q1;
u(q1);
if(chk_types(p,q1)==true)
{
expr r1=newtemp(p.datatype);
setatom(15,p,q1,r1);
add(r1,q);
}
else
{
cout<<"\nFailed in <Add>--->"<< p.index<<" is different from "<<q1.index;
reject();
}
}
else if(input.clas=="add_sub" || input.clas=="relop" || input.clas=="parenthesis_close" || input.clas=="semicolon" ||
input.clas=="comma")
{
q=p;
}
else reject();
}
void u(expr &p)
{
if(input.clas=="parenthesis_open" || input.clas=="id" || input.clas=="int_const" ||
input.clas=="long_const" )
{
expr p1;
v(p1);
multiply(p1,p);
}
else reject();
}
void multiply(expr p,expr &q)
{
if(input.clas=="mul_div_mod"
&& input.index==17 )
{
advanc();
expr q1;
v(q1);
if(chk_types(p,q1)==true)
{
expr r1=newtemp(p.datatype);
setatom(17,p,q1,r1);
multiply(r1,q);
}
else
{
cout<<"\nFailed in <Multiply>--->"<<p.index<<" is different from "<<q1.index;
reject();
}
}
else if(input.clas=="add_sub" || input.clas=="add_sub" || input.clas=="relop" || input.clas=="parenthesis_close" ||
input.clas=="semicolon" || input.clas=="comma" )
{
q=p;
}
else reject();
}
void v(expr &p)
{
if(input.clas=="parenthesis_open" || input.clas=="id" || input.clas=="int_const" || input.clas=="long_const")
{
expr p1;
w(p1);
divide(p1,p);
}
else reject();
}
void divide(expr p,expr &q)
{
if(input.clas=="mul_div_mod"
&& input.index==18)
{
advanc();
expr q1;
w(q1);
if(chk_types(p,q1)==true)
{
expr r1=newtemp(p.datatype);
setatom(18,p,q1,r1);
divide(r1,q);
}
else
{
cout<<"\nFailed in <Divide>--->"<<p.index<<" is different from "<<q1.index;
reject();
}
}
else if(input.clas=="mul_div_mod" || input.clas=="add_sub" || input.clas=="add_sub" || input.clas=="relop" ||
input.clas=="parenthesis_close" || input.clas=="semicolon" || input.clas=="comma")
{
q=p;
}
else reject();
}
void w(expr &p)
{
if(input.clas=="parenthesis_open" || input.clas=="id" || input.clas=="int_const" || input.clas=="long_const")
{
expr p1;
x(p1);
mod(p1,p);
}
else reject();
}
void mod(expr p,expr &q)
{
if(input.clas=="mul_div_mod"
&& input.index==19)
{
advanc();
expr q1;
x(q1);
if(chk_types(p,q1)==true)
{
expr r1=newtemp(p.datatype);
setatom(19,p,q1,r1);
mod(r1,q);
}
else
{
cout<<"\nFailed in <Mod>---> "<< p.index<<"is different from "<< q1.index;
reject();
}
}
else if(input.clas=="mul_div_mod" || input.clas=="mul_div_mod" || input.clas=="add_sub" || input.clas=="add_sub" ||
input.clas=="relop" || input.clas=="parenthesis_close" || input.clas=="semicolon" || input.clas=="comma")
{
q=p;
}
else reject();
}
void x(expr &p)
{
if(input.clas=="parenthesis_open")
{
advanc();
expression(p);
if(input.clas=="parenthesis_close")
advanc();
else reject();
}
else if(input.clas=="id")
{
long indx=chk_ident(input.index);
if(indx!=-10)
{
p.index=indx;
p.whichtable=table;
if(table==0)
p.datatype=syn_identifier[indx].datatype;
else if(table==1)
p.datatype=args_identifier[indx].datatype;
}
else
{
cout<<"\nFailed in <X>-->...."
<<" Variable "<<lex_identifier[input.index]<<" Not Found ";
reject();
}
advanc();
}
else if(input.clas=="int_const")
{
p.datatype=23;
p.index=input.index;
p.whichtable=3;
advanc();
}
else if(input.clas=="long_const")
{
p.datatype=24;
p.index=input.index;
p.whichtable=2;
advanc();
}
else reject();
}
///**********************///
///**********************///
/// ///
/// CODE GENERATOR ///
/// STARTED ///
///**********************///
///**********************///
//
//Code Generator's Globals
//
ofstream code(FILE_WRITE);
//ofstream code("C2ASM.txt");
bool collect_ebx=false;
///////////////////////////////////////////////
//
//Code Generator's Helper Fucntion Declarations
//
///////////////////////////////////////////////
//Used to ATTACH "g" to Global Variables.So,that they don't CLASH with Main()'s variables,Since
//I used to PUT all the Global And Main() Variables in .Data Segment of Assembly
void mangle_globals();
//If a Variable Appears inside some User Defined Function.It must be addressed by using [BP+..]
//In Short These and other situations,Where Name_Resolving is IMPORTANT this Function is called
string name_resolve(expr& e);
//It places All Global/Main() Variables in the Data Segment of Assembly Code.
void putvariables();
//It Converts a Long Number into String Object
string number2string(long count);
//It returns correct Jump condition for a Particular Relational Operator.
//Used By "CMP" ATOM only
string jcond4cmps(int& indx);
//It returns correct Jump condition for a Particular Relational Operator.
//Used By "JUMPF" ATOM only
string jcond4jumpf(int& indx);
//Following Functions are respective Mappings of ATOMS into Functions.
//Each of them get Called whenever ATOM of their respective type is seen.
void proc_marker(atom& atm);
void adds(atom& atm);
void assign(atom& atm);
void subs(atom& atm);
void mul(atom& atm);
void divs(atom& atm);
void label(atom& atm);
void jump(atom& atm);
void cmps(atom& atm);
void condjump(atom& atm);
void jumpf(atom& atm);
void call(atom& atm);
void param(atom& atm);
void returns(atom& atm);
//
//Code Generator's Helper Fucntion Definitions
//
void mangle_globals()
{
for(unsigned int i=0;i<syn_identifier.size();i++)
//Find only GLOBAL VARIABLES
if(syn_identifier[i].binding==-2 &&
syn_identifier[i].func_or_not==false)
{
syn_identifier[i].name="g"+syn_identifier[i].name;
}
}
void putvariables()
{
for(unsigned int i=0;i<syn_identifier.size();i++)
//OUTPUT only GLOBAL AND MAIN VARIABLES + Temporaries
if((syn_identifier[i].binding==-2 || syn_identifier[i].binding==-1)
&& syn_identifier[i].func_or_not==false)
{
//Deciding Whether it's a LONG or an INTEGER?
if(syn_identifier[i].datatype==0 ||syn_identifier[i].datatype==23)
//An INTEGER
code<<syn_identifier[i].name<<" dw "<<0<<endl;
else
//A LONG
code<<syn_identifier[i].name<<" dd "<<0<<endl;
}
}
void proc_marker(atom& atm)
{
switch(atm.arg1.datatype)
{
//For Start Of Fucntion
case 1:
{
switch(atm.arg1.index)
{
//It's main()
case -1:
code<<"main proc"<<endl
<<"mov eax,@data"<<endl
<<"mov ds,ax"<<endl;
break;
//It's an Ordinary Function
default:
code<<syn_identifier[atm.arg1.index].name
<<" proc"<<endl
<<"push bp"<<endl
<<"mov bp,sp"<<endl
<<"sub sp,"<<atm.arg1.whichtable<<endl;
}
}
break;
//For End Of Fucntion
case 0:
{
switch(atm.arg1.index)
{
//It's main()
case -1:
code<<"mov ax,4c00h"<<endl
<<"int 21h"<<endl
<<"main endp"<<endl;
break;
//It's an Ordinary Function
default:
code<<"add sp,"<<atm.arg1.whichtable<<endl
<<"pop bp"<<endl
<<"ret"<<endl
<<syn_identifier[atm.arg1.index].name
<<" endp"<<endl;
}
}
break;
default:
cout<<endl<<"Error in Fucntion Tagging";
exit(-1);
}
}
string name_resolve(expr& e)
{
string name;
switch(e.whichtable)
{
//Belongs to number_long
case 2:
name+=number2string(number_long[e.index]);
break;
//Belongs to number_int
case 3:
name+=number2string(number_int[e.index]);
break;
//Belongs to syn_identifier
case 0:
//If it Belongs to an Ordinary Fucntion
if(syn_identifier[e.index].offset!=-10)
{
name+="[bp-";
name+=number2string(syn_identifier[e.index].offset);
name+="]";
}
//else it Belongs to a main() or a global variable
else
name=syn_identifier[e.index].name;
break;
//Belongs to args_identifier
case 1:
name+="[bp+";
name+=number2string(args_identifier[e.index].offset);
name+="]";
break;
}
return name;
}
string number2string(long count)
{
char name[40];
char temp[40];
ltoa(count,temp,10);
strcpy(name,temp);
return string(name);
}
void adds(atom& atm)
{
//If its an INTEGER ADDITION use 16-Bit Registers
if(atm.result.datatype==0)
{
code<<"push cx"<<endl
<<"mov cx,0"<<endl
<<"mov cx,word ptr "<<name_resolve(atm.arg1)<<endl
<<"add cx,word ptr "<<name_resolve(atm.arg2)<<endl
<<"mov "<<name_resolve(atm.result)<<",cx"<<endl
<<"pop cx"<<endl;
}
//If its a LONG ADDITION use 32-Bit Registers
else
{
code<<"push ecx"<<endl
<<"mov ecx,0"<<endl
<<"mov ecx,dword ptr "<<name_resolve(atm.arg1)<<endl
<<"add ecx,dword ptr "<<name_resolve(atm.arg2)<<endl
<<"mov "<<name_resolve(atm.result)<<",ecx"<<endl
<<"pop ecx"<<endl;
}
}
void assign(atom& atm)
{
//If its an INTEGER ASSIGNMENT use 16-Bit Registers
if(atm.result.datatype==0)
{
/*If The assignment is taking PLACE immediately after FUNCTION
call,Then USE BX register from where data is to be copied*/
if(collect_ebx==true)
{
code<<"mov "<<name_resolve(atm.result)<<",bx"<<endl;
collect_ebx=false;
}
else
{
code<<"push cx"<<endl
<<"mov cx,0"<<endl
<<"mov cx,word ptr "<<name_resolve(atm.arg1)<<endl
<<"mov "<<name_resolve(atm.result)<<",cx"<<endl
<<"pop cx"<<endl;
}
}
//If its a LONG ASSIGNMENT use 32-Bit Registers
else
{
/*If The assignment is taking PLACE immediately after FUNCTION
call,Then USE EBX register from where data is to be copied*/
if(collect_ebx==true)
{
code<<"mov "<<name_resolve(atm.result)<<",ebx"<<endl;
collect_ebx=false;
}
else
{
code<<"push ecx"<<endl
<<"mov ecx,0"<<endl
<<"mov ecx,dword ptr "<<name_resolve(atm.arg1)<<endl
<<"mov "<<name_resolve(atm.result)<<",ecx"<<endl
<<"pop ecx"<<endl;
}
}
}
void subs(atom& atm)
{
//If its an INTEGER SUBTRACTION use 16-Bit Registers
if(atm.result.datatype==0)
{
code<<"push cx"<<endl
<<"mov cx,0"<<endl
<<"mov cx,word ptr "<<name_resolve(atm.arg1)<<endl
<<"sub cx,word ptr "<<name_resolve(atm.arg2)<<endl
<<"mov "<<name_resolve(atm.result)<<",cx"<<endl
<<"pop cx"<<endl;
}
//If its a LONG SUBTRACTION use 32-Bit Registers
else
{
code<<"push ecx"<<endl
<<"mov ecx,0"<<endl
<<"mov ecx,dword ptr "<<name_resolve(atm.arg1)<<endl
<<"sub ecx,dword ptr "<<name_resolve(atm.arg2)<<endl
<<"mov "<<name_resolve(atm.result)<<",ecx"<<endl
<<"pop ecx"<<endl;
}
}
void mul(atom& atm)
{
//If its an INTEGER MULTIPLICATION use 16-Bit Registers
if(atm.result.datatype==0)
{
code<<"push cx"<<endl
<<"mov cx,0"<<endl
<<"mov cx,word ptr "<<name_resolve(atm.arg1)<<endl
<<"mov "<<name_resolve(atm.result)<<",cx"<<endl
<<"mov cx,"<<name_resolve(atm.arg2)<<endl
<<"imul cx,word ptr "<<name_resolve(atm.result)<<endl
<<"mov "<<name_resolve(atm.result)<<",cx"<<endl
<<"pop cx"<<endl;
}
//If its a LONG MULTIPLICATION use 32-Bit Registers
else
{
code<<"push ecx"<<endl
<<"mov ecx,0"<<endl
<<"mov ecx,dword ptr "<<name_resolve(atm.arg1)<<endl
<<"mov "<<name_resolve(atm.result)<<",ecx"<<endl
<<"mov ecx,dword ptr "<<name_resolve(atm.arg2)<<endl
<<"imul ecx,"<<name_resolve(atm.result)<<endl
<<"mov "<<name_resolve(atm.result)<<",ecx"<<endl
<<"pop ecx"<<endl;
}
}
void divs(atom& atm)
{
//If its an INTEGER DIVISION use 16-Bit Registers
if(atm.result.datatype==0)
{
code<<"push ax"<<endl
<<"push cx"<<endl
<<"push dx"<<endl
<<"mov ax,0"<<endl
<<"mov cx,0"<<endl
<<"mov dx,0"<<endl
<<"mov ax,word ptr "<<name_resolve(atm.arg1)<<endl
<<"mov cx,word ptr "<<name_resolve(atm.arg2)<<endl
<<"div cx"<<endl
<<"mov "<<name_resolve(atm.result)<<",ax"<<endl
<<"pop dx"<<endl
<<"pop cx"<<endl
<<"pop ax"<<endl;
}
//If its a LONG DIVISION use 32-Bit Registers
else
{
code<<";Warning: Long Division is LOGICALLY FLAWED due to EAX"<<endl
<<"push eax"<<endl
<<"push ecx"<<endl
<<"push edx"<<endl
<<"mov eax,0"<<endl
<<"mov ecx,0"<<endl
<<"mov edx,0"<<endl
<<"mov eax,dword ptr "<<name_resolve(atm.arg1)<<endl
<<"mov ecx,dword ptr "<<name_resolve(atm.arg2)<<endl
<<"div ecx"<<endl
<<"mov "<<name_resolve(atm.result)<<",eax"<<endl
<<"pop edx"<<endl
<<"pop ecx"<<endl
<<"pop eax"<<endl;
}
}
void mods(atom& atm)
{
//If its an INTEGER MOD use 16-Bit Registers
if(atm.result.datatype==0)
{
code<<"push ax"<<endl
<<"push cx"<<endl
<<"push dx"<<endl
<<"mov ax,0"<<endl
<<"mov cx,0"<<endl
<<"mov dx,0"<<endl
<<"mov ax,word ptr "<<name_resolve(atm.arg1)<<endl
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -