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

📄 asmcodegenerator.cpp

📁 C-编译器的设计文档与源代码下载,1. 具有比较友好的GUI界面(仿照了我自己正在用的emacs); 2. 语法支持比较全面(毕竟是C-
💻 CPP
📖 第 1 页 / 共 2 页
字号:
				   "	.code\r\n"
				   ";_MAIN PROC\r\n"
				   "start		proc	far\r\n"
				   "	mov		ax, @data\r\n"
				   "	mov		ds, ax\r\n"
				   ";\r\n";
	emitCode( temp );

	CTreeNode* p = m_pAnalyzer->m_pProgram;
	while( p ) {
		if( p->nodekind == kFunDec && p->szName == "main" ) {
			genFunc( p ); break;
		}
		p = p->sibling;
	}
	p = m_pAnalyzer->m_pProgram;
	while( p ) {
		if( p->nodekind == kFunDec && p->szName != "main" ) {
			temp.Format( ";----------------------------------------------------\r\n"
						 "%s	proc	near pascal uses ax bx cx dx", (LPCTSTR)p->szName );// for parameters
			emitCode( temp );
			genFunc( p );
		}
		p = p->sibling;
	}
	// add general purpose routines
	_readi();
	_writei();
	// end of code segment
	temp = ";----------------------------------------------------\r\n"
		   "	end 	start\r\n";
	emitCode( temp );
}

// generate codes for one function
void CAsmCodeGenerator::genFunc( CTreeNode* pNode )
{
	CString temp;
	CTreeNode* p = pNode->child[0];
	if( pNode->szName != "main" )
		genLocal( pNode );
	p = pNode->child[1];
	while( p ) {
		genStmt( p );
		p = p->sibling;
	}
	if( pNode->szName == "main" )
		temp.Format( "	mov 	ax, 4c00h\r\n"
					 "	int		21h\r\n"
					 "start		endp\r\n" );
	else
		temp.Format( "	ret\r\n"
					 "%s	endp\r\n", (LPCTSTR)pNode->szName );
	emitCode( temp );
}

// generate local variables
void CAsmCodeGenerator::genLocal( CTreeNode* pNode )
{
	BOOL first = TRUE;
	CString local = _T(""), temp, temp2;
	CTreeNode* p = pNode->child[0];// parameters
	while( p ) {
		temp.Format( ", %s@%s:word", (LPCTSTR)p->szScope, (LPCTSTR)p->szName );
		emitCode( temp );
		p = p->sibling;
	}
	temp = "\r\n"; emitCode( temp );

	p = pNode->child[1];// make local variables
	while( p ) {
		if( p->nodekind == kVarDec ) {
			if( p->bArray ) temp2.Format( "%s@%s[%d]:word", (LPCTSTR)p->szScope, (LPCTSTR)p->szName, p->iArraySize );
			else temp2.Format( "%s@%s:word", (LPCTSTR)p->szScope, (LPCTSTR)p->szName );
			if( first ) {
				first = FALSE;
				temp.Format( "\tlocal\t%s", (LPCTSTR)temp2 );
			} else
				temp.Format( ", %s", (LPCTSTR)temp2 );
			local += temp;
		}
		p = p->sibling;
	}
	if( !first ) emitCode( local + "\r\n" );
}

void CAsmCodeGenerator::genStmt( CTreeNode* p, int lab1, int lab2 )
{
	CTreeNode* t = NULL;
	int i, _lab1, _lab2;
	CString temp = _T("");

	if( p == NULL ) return;
	switch( p->nodekind ) {
	case kStmt:
		switch( p->kind.stmt ) {
		case kRead:
			emitComment( "read statement" );
			// read in a char or a num
			if( p->type == _CHAR ) _inline_readc();
			else emitCode( "call\t_call_readi_" );
			// store
			t = p->child[0];
			if( t->bArray ) {
				emitCode( "push\tax" );
				if( isAddr(t) ) emitCode( "mov \tbx, %s@%s", (LPCTSTR)t->szScope, (LPCTSTR)t->szName );
				else emitCode( "lea \tbx, %s@%s", (LPCTSTR)t->szScope, (LPCTSTR)t->szName );
				emitCode( "push\tbx" );
				genStmt( t->child[0] );
				emitCode( "pop \tsi" );
				emitCode( "add \tsi, si" );// all use "WORD"
				emitCode( "pop \tbx" );
				emitCode( "pop \tax" );
				emitCode( "mov \t[bx + si], ax" );
			} else
				emitCode( "mov \t%s@%s, ax", (LPCTSTR)t->szScope, (LPCTSTR)t->szName );
			break;
		case kWrite:
			emitComment( "write statement" );
			t = p->child[0];
			if( p->type == _CHAR || p->type == _CHARACTER ) {
				if( t->nodekind == kExp && t->kind.exp == kConst ) {
					emitCode( "mov \tah, 2" );
					emitCode( "mov \tdl, '%c'", t->szName[0] );
				} else {
					genStmt( t );
					emitCode( "pop \tdx" );
					emitCode( "mov \tah, 2" );
				}
				emitCode( "int \t21h" );
			} else {
				genStmt( t );
				emitCode( "pop \tbx" );
				emitCode( "call\t_call_showi_" );
			}
			break;
		case kPrintf:
			emitComment( "printf statement" );
			emitCode( "push\tax" );
			emitCode( "push\tdx" );
			emitCode( "mov \tah, 2" );
			for( i = 0; i < p->szName.GetLength(); i++ ) {
				if( p->szName[i] == '\n' ) {
					temp = "	mov		dl, 00ah\r\n"
						   "	int		21h\r\n"
						   "	mov		dl, 00dh\r\n"
						   "	int		21h\r\n";
					emitCode( temp );
				} else {
					emitCode( "mov \tdl, %.3xh", (int)p->szName[i] );
					emitCode( "int \t21h" );
				}
			}
			emitCode( "pop \tdx" );
			emitCode( "pop \tax" );
			emitComment( "end of printf statement" );
			break;
		case kLabel:
			emitComment( "label %s@%s", (LPCTSTR)p->szScope, (LPCTSTR)p->szName );
			emitLabel( "%s@%s:", (LPCTSTR)p->szScope, (LPCTSTR)p->szName );
			break;
		case kGoto:
			emitComment( "goto %s@%s", (LPCTSTR)p->szScope, (LPCTSTR)p->szName );
			emitCode( "jmp \t%s@%s", (LPCTSTR)p->szScope, (LPCTSTR)p->szName );
			break;
		case kIf:
			emitComment( "start of if statement" );
			emitComment( "if conditions" );
			t = p->child[0];
			genStmt( t );
			emitCode( "pop \tax" );
			emitCode( "cmp \tax, 0" );
			_lab1 = label++;
			emitCode( "je  \tL%d", _lab1 );
			emitComment( "if statements" );
			t = p->child[1];
			while( t ) {
				genStmt( t, lab1, lab2 ); t = t->sibling;
			}
			if( p->child[2] ) {
				_lab2 = label++;
				emitCode( "jmp \tL%d", _lab2 );
			}
			emitLabel( "L%d:", _lab1 );
			if( p->child[2] ) {
				emitComment( "else statements" );
				t = p->child[2];
				while( t ) {
					genStmt( t, lab1, lab2 ); t = t->sibling;
				}
				emitLabel( "L%d:", _lab2 );
			}
			emitComment( "end of if statement" );
			break;
		case kWhile:
			emitComment( "start of while statement" );
			_lab1 = label++;
			emitLabel( "L%d:", _lab1 );
			emitComment( "while conditions" );
			t = p->child[0];
			genStmt( t );
			emitCode( "pop \tax" );
			emitCode( "cmp \tax, 0" );
			_lab2 = label++;
			emitCode( "je  \tL%d", _lab2 );
			emitComment( "while statements" );
			t = p->child[1];
			while( t ) {
				genStmt( t, _lab1, _lab2 ); t = t->sibling;
			}
			emitCode( "jmp \tL%d", _lab1 );
			emitLabel( "L%d:", _lab2 );
			emitComment( "end of while statement" );
			break;
		case kBreak:
			emitComment( "break statement" );
			emitCode( "jmp \tL%d", lab2 );
			break;
		case kContinue:
			emitComment( "continue statement" );
			emitCode( "jmp \tL%d", lab1 );
			break;
		case kReturn:
			emitComment( "return statement" );
			if( p->child[0] && p->szName != "main" ) {
				genStmt( p->child[0] );
				emitCode( "pop \tax" );
				emitCode( "mov \t_return, ax" );
			}
			if( p->sibling ||
				(p->father && p->father->nodekind != kFunDec) )
				emitCode( "ret" );
			break;
		case kCall:
			emitComment( "call '%s(...)'", (LPCTSTR)p->szName );
			t = p->child[0];
			while( t ) {
				genStmt( t ); t = t->sibling;
			}
			emitCode( "call\t%s", (LPCTSTR)p->szName );
			if( p->type != _VOID ) {
				emitCode( "mov \tax, _return" );
				emitCode( "push\tax" );
			}
			break;
		}
		break;
	case kExp:
		switch( p->kind.exp ) {
		case kConst:
			if( p->type == _CHARACTER ) {
				emitCode( "mov \tal, '%c'", p->szName[0] );
				emitCode( "mov \tah, 0" );
			} else
				emitCode( "mov \tax, %s", (LPCTSTR)p->szName );
			emitCode( "push\tax" );
			break;
		case kID:
			if( p->bArray ) {
				if( isAddr(p) )
					emitCode( "mov \tbx, %s@%s", (LPCTSTR)p->szScope, (LPCTSTR)p->szName );
				else
					emitCode( "lea \tbx, %s@%s", (LPCTSTR)p->szScope, (LPCTSTR)p->szName );
				if( p->father && p->father->nodekind == kStmt && p->father->kind.stmt == kCall )
					emitCode( "mov \tax, bx" );// passing its base-address to the call function is OK
				else {
					genStmt( p->child[0] );
					emitCode( "pop \tsi" );
					emitCode( "add \tsi, si" );// all use "WORD"
					emitCode( "mov \tax, [bx + si]" );
				}
			} else
				emitCode( "mov \tax, %s@%s", (LPCTSTR)p->szScope, (LPCTSTR)p->szName );
			emitCode( "push\tax" );
			break;
		case kOp:
			if( p->szName == "=" ) {
				if( p->father && p->father->szName == "=" && p->father->child[0] == p )
					break; // continuous ASSIGN the same ID
				emitComment( "" );
				genStmt( p->child[1] );
				// process the left-hand of "="
				t = p->child[0];
				while( t && (t->nodekind != kExp || t->kind.exp != kID) ) t = t->child[0];
				if( t->bArray ) {
					if( isAddr(t) )
						emitCode( "mov \tbx, %s@%s", (LPCTSTR)t->szScope, (LPCTSTR)t->szName );
					else
						emitCode( "lea \tbx, %s@%s", (LPCTSTR)t->szScope, (LPCTSTR)t->szName );
					genStmt( t->child[0] );
					emitCode( "pop \tsi" );
					emitCode( "add \tsi, si" );
					emitCode( "add \tbx, si" );
					emitCode( "pop \tax" );
					emitCode( "mov \t[bx], ax" );
				} else {
					emitCode( "pop \tax" );
					emitCode( "mov \t%s@%s, ax", (LPCTSTR)t->szScope, (LPCTSTR)t->szName );
				}
			} else if( p->szName == "!" ) {
				genStmt( p->child[0] );
				_lab1 = label++; _lab2 = label++;
				temp.Format( "	pop		ax\r\n"
						     "	cmp		ax, 0\r\n"
						     "	je		__not@@%d\r\n"
						     "	mov		ax, 0\r\n"
						     "	jmp		__not@@%d\r\n"
							 "__not@@%d:\r\n"
							 "	mov		ax, 1\r\n"
							 "__not@@%d:\r\n", _lab1, _lab2, _lab1, _lab2 );
				emitCode( temp );
			} else {
				// binary operations
				genStmt( p->child[0] );
				genStmt( p->child[1] );
				emitCode( "pop \tbx" );
				emitCode( "pop \tax" );
				if( p->szName == "==" ) {
					_lab1 = label++; _lab2 = label++;
					temp.Format( "	sub		ax, bx\r\n"
								 "	cmp		ax, 0\r\n"
								 "	je		__eq@@%d\r\n"
								 "	mov		ax, 0\r\n"
								 "	jmp		__eq@@%d\r\n"
								 "__eq@@%d:\r\n"
								 "	mov		ax, 1\r\n"
								 "__eq@@%d:\r\n", _lab1, _lab2, _lab1, _lab2 );
					emitCode( temp );
				} else if( p->szName == "!=" ) {
					_lab1 = label++;
					temp.Format( "	sub		ax, bx\r\n"
								 "	cmp		ax, 0\r\n"
								 "	je		__neq@@%d\r\n"
								 "	mov		ax, 1\r\n"
								 "__neq@@%d:\r\n", _lab1, _lab1 );
					emitCode( temp );
				} else if( p->szName == "<" ) {
					_lab1 = label++; _lab2 = label++;
					temp.Format( "	sub		ax, bx\r\n"
								 "	cmp		ax, 0\r\n"
								 "	jl		__lt@@%d\r\n"
								 "	mov		ax, 0\r\n"
								 "	jmp		__lt@@%d\r\n"
								 "__lt@@%d:\r\n"
								 "	mov		ax, 1\r\n"
								 "__lt@@%d:\r\n", _lab1, _lab2, _lab1, _lab2 );
					emitCode( temp );
				} else if( p->szName == "<=" ) {
					_lab1 = label++; _lab2 = label++;
					temp.Format( "	sub		ax, bx\r\n"
								 "	cmp		ax, 0\r\n"
								 "	jle		__ngt@@%d\r\n"
								 "	mov		ax, 0\r\n"
								 "	jmp		__ngt@@%d\r\n"
								 "__ngt@@%d:\r\n"
								 "	mov		ax, 1\r\n"
								 "__ngt@@%d:\r\n", _lab1, _lab2, _lab1, _lab2 );
					emitCode( temp );
				} else if( p->szName == ">=" ) {
					_lab1 = label++; _lab2 = label++;
					temp.Format( "	sub		ax, bx\r\n"
								 "	cmp		ax, 0\r\n"
								 "	jge		__nlt@@%d\r\n"
								 "	mov		ax, 0\r\n"
								 "	jmp		__nlt@@%d\r\n"
								 "__nlt@@%d:\r\n"
								 "	mov		ax, 1\r\n"
								 "__nlt@@%d:\r\n", _lab1, _lab2, _lab1, _lab2 );
					emitCode( temp );
				} else if( p->szName == ">" ) {
					_lab1 = label++; _lab2 = label++;
					temp.Format( "	sub		ax, bx\r\n"
								 "	cmp		ax, 0\r\n"
								 "	jg		__gt@@%d\r\n"
								 "	mov		ax, 0\r\n"
								 "	jmp		__gt@@%d\r\n"
								 "__gt@@%d:\r\n"
								 "	mov		ax, 1\r\n"
								 "__gt@@%d:\r\n", _lab1, _lab2, _lab1, _lab2 );
					emitCode( temp );
				} else if( p->szName == "+" )
					emitCode( "add \tax, bx" );
				else if( p->szName == "-" )
					emitCode( "sub \tax, bx" );
				else if( p->szName == "*" )
					emitCode( "imul\tbx" );
				else if( p->szName == "/" )
					emitCode( "idiv\tbx" );
				else if( p->szName == "&&" )
					emitCode( "and \tax, bx" );
				else if( p->szName == "||" )
					emitCode( "or  \tax, bx" );
			}
			// situations
			t = p->father;
			if( t && (t->nodekind == kExp || (t->nodekind == kStmt && p == t->child[0])) )
				emitCode( "push\tax" );
			break;
		}
		break;
	}
}

// check if pNode->szName is an address
// in this simple situation, pNode->szName is a parameter passed as array address
BOOL CAsmCodeGenerator::isAddr( CTreeNode* pNode )
{
	if( !pNode || pNode->nodekind != kExp || pNode->kind.exp != kID ) return FALSE;
	CTreeNode* p = pNode->father;
	while( p && p->nodekind != kFunDec ) p = p->father;
	CTreeNode* t = p->child[0];// parameters
	while( t ) {
		if( t->bArray && t->szName == pNode->szName ) return TRUE;
		t = t->sibling;
	}
	return FALSE;
}

⌨️ 快捷键说明

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