📄 asmgen.cpp
字号:
#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 + -