📄 asmcodegenerator.cpp
字号:
" .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 + -