⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 asmgen.cpp

📁 C-MINUS编译器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "asmGen.h"

/**:	File: asmGen.cpp
&
*	This is 80X86 ASM code generator implate
*
*	author:	lonelyforest
*	data:	2006.4.24
&
*       与2006.5.10最终修正完成。
*/


//-----------------------------------------------------------------------------
asmGen::asmGen(const string &filename):codefile(filename),
analyze(NULL), tree_(NULL), traceCode(true),is_good_(true)
{
	err = 0;
	warn= 0;
	cL	= 0;
	
	int pos = codefile.rfind('.');
	codefile.erase(pos, codefile.length()-1);
	codefile += ".asm";
	
    analyze = new Analyzer(filename);
}


asmGen::~asmGen()
{
	if (code_.is_open() && (is_good())) {
		emitCode("\n\n;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"
			";\tThis file has bug while compiling, so, use it carafully!\n"
			"; developer remind of you don't ot use, a good idea is not use it, \n"
			"; if you report the bug to the developer, will very thank you!!!\n"
			";+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
	}
	
	if (analyze)         delete analyze;
	// don't delete tree_!!
}

/**:	Fun: asmGen::codeGen()
&
*	This is 80X86 ASM code generator primary interface
*
*	author:	lonelyforest
*	data:	2006.4.24
*/
//-----------------------------------------------------------------------------
void asmGen::codeGen()
{
    if (analyze){
        analyze->getSymbolFile();  // build syntax tree, symbol table, fun check ...
    } else {
		is_good_ = false;
		err++;
        outputMsg(-1, "some expection happened when analyze::getSymbolFile() !");
    }
	
    if (is_good())
    {
        // confirm has no error,
        outputMsg(-1, "80x86 ASM code generating ......");
		
        code_.open(codefile.c_str());
        if (!code_)  // create code file fail
        {
			is_good_ = false;
			err++;
			sprintf(msg_temp,
                "create code file \"%s\" fail ... generating x86ASM code stopping ...",
                codefile.c_str());
			outputMsg(-1, msg_temp);
		}
		else
		{
            // primary here
            x86Gen();
            sprintf(msg_temp,
				"80x86 ASM Code has save to \"%s\"...",
				codefile.c_str());
            outputMsg(-5,msg_temp);
		}
    }
    else
    {
        is_good_ = false;
		warn++;
        outputMsg(-1,
            "error(s) occur before 80x86 ASM code generating....."
            " code  generating stop ...");
    }
}

/**:	Fun: asmGen::x86Gen()
&
*	This is main part of 80X86 ASM code generator
*
*	author:	lonelyforest
*	data:	2006.4.24
*/
//-----------------------------------------------------------------------------
void asmGen::x86Gen()
{
    tree_ = analyze->program;
    if (tree_) {
        x86GenPre();        // generate stack, data, and program messages
        x86GenCode();       // generate functions
    }
    else
    {
		is_good_ = false;
		err++;
        outputMsg(-1, "Some error(s) occur before 80x86 ASM code generating.....");
        outputMsg(-1, "80x86 ASM generator get a empty syntax tree!!!!");
    }
}

/**:	Fun: asmGen::x86GenPre()
&
*	This program to create 80x86 asm file data segment
*   define varibles and  stack ...
*
*	author:	lonelyforest
*	data:	2006.4.25
*/
//-----------------------------------------------------------------------------
void asmGen::x86GenPre()
{
    string preMsg;
    
    emitComment(";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"
		";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;" );
    emitComment( "\n;File: ");
    emitCode( codefile.c_str());    // need no ';' again
	
    preMsg =
		"\n;"
		"\n;NOTE: This ASM file is generated by: \n"
		";                  Simple C minus Compiler     v1.0\n"
		";      CopyRight (C) 2002-2008 Lonelyforest. All rights reseved.\n"
		";\n"
		"; Because its not perfect, so this file maybe have bug! use it carefully!\n"
		";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n"
		";*****************************************************************************\n"
		"       .model  small\n"
		"       .586					;maybe use Pentium instructions\n"
		";*****************************************************************************\n"
		"stacksg	segment	para	stack	'stack'\n"
		"           dw	200h	dup(0)\n"       // 512 Bytes of stack space
		"	tos	label   word			;pointer to stack top\n"
		"stacksg	ends\n"
		";*****************************************************************************\n"
		"datasg	segment	para	'data'\n"
		" 	re_val		dw	0 			;return values\n"
		";other	global variables and main varibales\n";
	
    emitCode(preMsg.c_str());
    // other data
    TreeNode *p = NULL,
		*t = NULL;
	p = tree_;   // should assert (t)
	
	// 或者应该直接用 symbolTable 来获得数据;
	while (p) {
		if (p->nodekind == varK) {
			x86GenData(p);
		}
		else if (p->name == "main") {// local variable in _main, see it global
			t = p->child[1];    // void main(void), needn't child [0];
			while (t) {
				if (t->nodekind == varK) {
					x86GenData(t);
				}
				
				t = t->sibling;
			}
		}
		
		p = p->sibling;
	}
	
    // end of data segement
    preMsg =
        "datasg	ends					;end of data segment\n";
    emitCode(preMsg.c_str());
}

/**:	Fun: asmGen::x86GenCode()
&
*	This is code generator of 80X86 ASM code generator
*   create  code segment, and processes...
*
*	author:	lonelyforest
*	data:	2006.4.25
*/
//-----------------------------------------------------------------------------
void asmGen::x86GenCode()
{
    //...
    string codeMsg;
    codeMsg =
        ";*****************************************************************************\n"
        "codesg	segment	para 'code'\n"
        ";\n"
		";-----------------------------------------------------------------------------\n"
		";			begin\n"
		";		=======================\n"
		";\n"
		";main part of program, void main(void)\n"
        ";-----------------------------------------------------------------------------\n"
        "begin	proc    far\n"
        "	assume cs:codesg, ds:datasg, ss:stacksg\n"
        ";set SS register to current stack segment\n"
        "       mov     ax, stacksg\n"
        "       mov     ss, ax\n"
        "       mov     sp, offset tos\n"
        ";set up stack for return\n"
        "       push	ds				;save old data segment\n"
        "       sub	ax, ax				;put zore in AX\n"
        "       push	ax				;save it on stack\n"
        ";set DS register to current data segment\n"
        "       mov	ax, datasg			;data segment addr\n"
        "       mov	ds, ax				; into DS register\n"
        "       mov	es, ax				; into ES register\n"
        ";main part of program goes here\n"
        ";\n\n";
    emitCode(codeMsg.c_str());
    // main function ....
    TreeNode *p = NULL,
		*t = NULL;
    p  = tree_;
    while (p)
    {
		if (p->nodekind == funK && p->name == "main")
		{
			x86GenFun(p, false);
			break;
		}
		p = p->sibling;
    }
    
    if (!p) {       // should never happen!!
		err++;
		warn++;
		is_good_ = false;
		outputMsg(-1, "unfind extern _main in syntax tree!");
		throw "unfind extern _main in syntax tree!";
    }
    
    codeMsg =
		"\n	pop     ax\n"
		"	pop     ds\n"
		";\n"
        "	mov	ax, 4c00h			;return to DOS\n"
        "	int     21h\n"
        ";\n"
        "begin  endp					;end of begin prco\n";
    emitCode(codeMsg.c_str());
    // end main function
    
    // x86GenFun here....
    p = tree_;
    while (p)
    {
		if (p->nodekind == funK && p->name != "main")
		{
			x86GenFun(p, true);
		}
		
		p = p->sibling;
    }
	
    read_int();
    write_int();
    
    // ok, all done.. end of code segment
    codeMsg=
		";\n;-----------------------------------------------------------------------------\n"
        ";\ncodesg	ends					;end of code segment\n"
        ";*****************************************************************************\n"
		"      end	begin				;end assembly\n";
    emitCode( codeMsg.c_str());
}

/**:	Fun: asmGen::x86GenData(TreeNode *tree)
&
*	generator global variables and main variables
*
*	author:	lonelyforest
*	data:	2006.4.27
*/
//-----------------------------------------------------------------------------
void asmGen::x86GenData(TreeNode *tree)
{
	sprintf(msg_temp, "\t %s_%s_ \t dw",
		tree->scope.c_str(),tree->name.c_str());
	emitCode(msg_temp);
	
	if (tree->bArr) {
		sprintf(msg_temp, "\t %d \t dup(0)\n", tree->iArrSize);
		emitCode(msg_temp);
	}
	else
	{
		emitCode("\t0\n");
	}
}

/**:	Fun: asmGen::x86GenFun(TreeNode *tree, bool pre)
&
*	generate functions code
*
*	author:	lonelyforest
*	data:	2006.4.27
*/
//-----------------------------------------------------------------------------
void asmGen::x86GenFun(TreeNode *tree, bool pre)
{
	string funName= "_?????_????__\n";
	string codeStr =
		";\n"
		";-----------------------------------------------------------------------------\n";
	TreeNode *p = tree->child[0];
	if (pre)                  // main function
	{
		emitCode(codeStr.c_str());
		sprintf(msg_temp,"_%s_%s__",
			tree->name.c_str(), ((tree->type == k_INT) ? "int" : "void"));
		funName = msg_temp;
		sprintf(msg_temp,";\t\t\t%s\n",funName.c_str());
		emitCode(msg_temp);
		emitCode(";		=============================\n;\n");
		emitCode(";-----------------------------------------------------------------------------\n");
		sprintf(msg_temp,"%s\tproc\tnear\tfortran uses bx cx dx si di", funName.c_str());
		emitCode(msg_temp);
		
		if (!p) {
			emitCode("\n");
		}
		else {  // paramenters generate
			TreeNode *t = p;
			codeStr=",\n\t\t\t";
			sprintf(msg_temp, "%s%s_%s_:word",
				codeStr.c_str(),
				t->scope.c_str(),
				t->name.c_str());
			codeStr = msg_temp;
			t = t->sibling;
			
			while (t){
				sprintf(msg_temp, ", %s_%s_:word",
					t->scope.c_str(),
					t->name.c_str());
				codeStr += msg_temp;
				t = t->sibling;
			}
			
			emitCode(codeStr.c_str());
			emitCode("\n");
		}
		
		p = tree->child[1];
		x86GenVar(p);
		emitComment("\n");
	}
	
	p=tree->child[1];
	while (p)
	{
		x86GenSE(p);
		p = p->sibling;
	}
	
	if (pre)
	{
		sprintf(msg_temp, "%s%s\tendp\t\t\t\t;end of %s\n", 
			(tree->type == k_VOID) ? "\tret\n" : "", funName.c_str(), funName.c_str());
		emitCode(msg_temp);
	}
}

/**:	Fun: asmGen::x86GenVarLoc(TreeNode *tree)
&
*	generate local variables
*
*       那天看《IBM-PC 汇编语言程序设计》时突然看到,可以用local 来产生局部
*   临时变量,太好了,正好解决了函数内部的变量问题。
*
*	author:	lonelyforest
*	data:	2006.4.27
*/
//-----------------------------------------------------------------------------
void asmGen::x86GenVar(TreeNode *tree)
{
	//....
	string codeStr;
	TreeNode *t = tree;
	if (t && t->nodekind == varK) {
		if (t->bArr) {
			sprintf(msg_temp, "\tlocal\t%s_%s_[%d]:word",
				t->scope.c_str(), t->name.c_str(),
				t->iArrSize);
		} else {
			sprintf(msg_temp, "\tlocal\t%s_%s_:word",
				t->scope.c_str(), t->name.c_str());
		}
		codeStr = msg_temp;
		
		t = t->sibling;
		
		while (t && t->nodekind == varK)
		{
			if (t->bArr) {
				sprintf(msg_temp,
					", %s_%s_[%d]:word",
					t->scope.c_str(), t->name.c_str(),t->iArrSize);
			} else {
				sprintf(msg_temp,
					", %s_%s_:word",
					t->scope.c_str(),t->name.c_str());
			}
			
			codeStr += msg_temp;
			t = t->sibling;
		}
		
		emitCode(codeStr.c_str());
		emitCode("\n");
	}
}



/**:	Fun: asmGen::x86GenSE(TreeNode *tree)
&
*	generate stmt_exp_list code in functions
*
*	author:	lonelyforest
*	data:	2006.4.27
*/
//-----------------------------------------------------------------------------
void asmGen::x86GenSE(TreeNode *tree)
{
	//...
	if (tree && tree->nodekind == stmtK)
	{
		x86GenStmt(tree);
	}
	else if (tree && tree->nodekind == expK)
	{
		x86GenExp(tree);
	}
	else
	{
		//////////////////////////////////////////////////////////////////////////
	}
}

/**:	Fun: asmGen::x86GenStmt(TreeNode *tree)
&
*	generate stmt_list code in functions
*
*	author:	lonelyforest
*	data:	2006.4.27
*/
//-----------------------------------------------------------------------------
void asmGen::x86GenStmt(TreeNode *tree)
{
	//...
	if (tree) {
		int		curL = cL;	// current Label;
		int		curL1 = cL+1;
		TreeNode *p = tree;
		TreeNode *t = NULL;
		string funname = "_??????_????__";
		
		switch (p->kind.stmt ){
		case readK:
			emitComment("read statement\n");
			emitCode("\tcall\t__read_int_\n");
			// read result in BX register
			t = p->child[0];
			if (t->bArr){
                emitCode("\tpush\tbx\n");
                if (isLeft(t) ) {
                    sprintf(msg_temp, "\tmov\tbx, %s_%s_\n", t->scope.c_str(), t->name.c_str());
                    emitCode(msg_temp);
                }
                else {
                    sprintf(msg_temp, "\tlea\tbx, %s_%s_\n", t->scope.c_str(), t->name.c_str());
                    emitCode(msg_temp);
                }

                emitCode("\tpush\tbx\n");
                x86GenExp(t->child[0]);
				emitCode("\tmov\tsi, ax\n\tadd\tsi, si\n"
                            "\tpop\tbx\n\tpop\tax\n"
                            "\tmov\t[bx + si], ax\t\t;store result read\n");

			}
			else{   // not array
				 sprintf(msg_temp,
					"\tmov\t%s_%s_, bx\t\t\t;store result read\n",
					t->scope.c_str(), t->name.c_str());
				emitCode(msg_temp);
			}
			break;
		case writeK:
			emitComment("write statement\n");
			/// .... 
			t = p->child[0];
			x86GenSE(t);
			emitCode("\tmov\tbx, ax\n");
			emitCode("\tcall\t__write_int_\n");
			break;
		case ifK:
			cL+=2;
			emitComment(">>>== if statement\n");
			// .... condition of if 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -