?? zasm.cpp
字號:
// ---- 堆棧處理
// Push Source
iInstrIndex = AddInstrLookup( "Push", INSTR_PUSH, 1 );
SetOpType( iInstrIndex, 0, OP_FLAG_TYPE_MEM_REF |
OP_FLAG_TYPE_REG |
OP_FLAG_TYPE_INT |
OP_FLAG_TYPE_FLOAT |
OP_FLAG_TYPE_STRING );
// Pop Destination
iInstrIndex = AddInstrLookup( "Pop", INSTR_POP, 1 );
SetOpType( iInstrIndex, 0, OP_FLAG_TYPE_MEM_REF |
OP_FLAG_TYPE_REG );
// ---- 函數調用
// Call FunctionName
iInstrIndex = AddInstrLookup( "Call", INSTR_CALL, 1 );
SetOpType( iInstrIndex, 0, OP_FLAG_TYPE_FUNC_NAME );
// Ret
iInstrIndex = AddInstrLookup( "Ret", INSTR_RET, 0 );
// CallHost FunctionName
iInstrIndex = AddInstrLookup( "CallHost", INSTR_CALLHOST, 1 );
SetOpType( iInstrIndex, 0, OP_FLAG_TYPE_HOST_API_CALL );
// ---- 程序控制
// Pause Duration
iInstrIndex = AddInstrLookup( "Pause", INSTR_PAUSE, 1 );
SetOpType( iInstrIndex, 0, OP_FLAG_TYPE_INT |
OP_FLAG_TYPE_FLOAT |
OP_FLAG_TYPE_STRING |
OP_FLAG_TYPE_MEM_REF |
OP_FLAG_TYPE_REG );
// Exit Code
iInstrIndex = AddInstrLookup( "Exit", INSTR_EXIT, 1 );
SetOpType( iInstrIndex, 0, OP_FLAG_TYPE_INT |
OP_FLAG_TYPE_FLOAT |
OP_FLAG_TYPE_STRING |
OP_FLAG_TYPE_MEM_REF |
OP_FLAG_TYPE_REG );
}
/*****************************************************************************************
*
* AddInstrLookup()
*
* 向指令查找表添加指令
*/
int AddInstrLookup( char *pstrMnemonic, int iOpCode, int iOpCount )
{
// 用靜態變量保存查找表中下一條指令的索引
static int s_iInstrIndex = 0;
// 檢測指令索引是否超出查找表的范圍
if( s_iInstrIndex >= MAX_INSTR_LOOKUP_COUNT )
return -1;
// 設置指令助記符、操作碼和操作數計數字段
strcpy( g_InstrTable[s_iInstrIndex].pstrMnemonic, pstrMnemonic );
_strupr( g_InstrTable[s_iInstrIndex].pstrMnemonic );
g_InstrTable[s_iInstrIndex].iOpcode = iOpCode;
g_InstrTable[s_iInstrIndex].iOpCount = iOpCount;
// 為操作數類型數組分配空間
g_InstrTable[s_iInstrIndex].OpList = new OpTypes[iOpCount];
// 返回當前指令在指令查找表中的索引,后移索引
int iRetInstrIndex = s_iInstrIndex;
++ s_iInstrIndex;
return iRetInstrIndex;
}
/*****************************************************************************************
*
* SetOpType()
*
* 設定操作數類型列表
*/
void SetOpType( int iInstrIndex, int iOpIndex, OpTypes iOpType )
{
g_InstrTable[iInstrIndex].OpList[iOpIndex] = iOpType;
}
/*****************************************************************************************
*
* GetInstrByMnemonic
*
* 根據指令助記符取得指令查找表節點
*/
bool GetInstrByMnemonic( char *pstrMnemonic, InstrLookup *pInstr )
{
for( int i=0 ; i<MAX_INSTR_LOOKUP_COUNT ; ++ i )
{
// 比較指令助記符
if( strcmp( g_InstrTable[i].pstrMnemonic, pstrMnemonic ) == 0 )
{
*pInstr = g_InstrTable[i];
return true;
}
}
// 匹配不成功
return false;
}
/*****************************************************************************************
*
* PrintLogo()
*
* 打印歡迎界面
*/
void PrintLogo()
{
printf ( "ZASM\n\n" );
printf ( "ZScript 匯編器\n\n" );
printf ( "版本:\t%d.%d\n", VERSION_MAJOR, VERSION_MINOR );
printf ( "作者:\t張錦\n" );
printf ( "\n" );
}
/*****************************************************************************************
*
* PrintUsage()
*
* 打印用法
*/
void PrintUsage()
{
printf( "Usage:\tZASM Source.ZASM [Executable.ZSE]\n" );
printf( "\n" );
printf( "\t- 文件擴展名不是必須的\n" );
printf( "\t- 可執行文件名是可選的,默認文件名為 源文件名.ZSE\n" );
system("pause");
}
/*****************************************************************************************
*
* void Init()
*
* 初始化
*/
void Init()
{
// 初始化指令查找表
InitInstrTable();
// 初始化其他表
InitLinkedList( &g_FuncTable );
InitLinkedList( &g_StringTable );
InitLinkedList( &g_SymbolTable );
InitLinkedList( &g_LabelTable );
InitLinkedList( &g_HostAPICallTable );
}
/*****************************************************************************************
*
* void ShutDown()
*
* 關閉
*/
void ShutDown()
{
}
/*****************************************************************************************
*
* LoadSourceFile()
*
* 讀取源代碼
*/
void LoadSourceFile()
{
// 已二進制方式讀取源文件
g_pSourceFile = fopen( g_pstrSourceFileName, "rb" );
if( !g_pSourceFile )
ExitOnError( "無法打開源文件" );
// 統計代碼行數
while( !feof(g_pSourceFile) )
{
if( fgetc(g_pSourceFile) == '\n' )
{
++ g_iSourceCodeSize;
}
}
++ g_iSourceCodeSize;
// 關閉二進制方式打開的源文件
fclose( g_pSourceFile );
// 為源代碼緩存分配空間
g_ppstrSourceCode = new char*[ g_iSourceCodeSize ];
if( !g_ppstrSourceCode )
ExitOnError( "沒有足夠的空間非配給 g_ppstrSourceCode " );
// 再次以 ASCII方式 打開源文件
g_pSourceFile = fopen( g_pstrSourceFileName, "r" );
if( !g_pSourceFile )
ExitOnError( "無法打開源文件" );
// 逐行處理源文件
for( int iCurrLineIndex = 0 ; iCurrLineIndex < g_iSourceCodeSize ; ++ iCurrLineIndex )
{
// 為代碼行非配空間
g_ppstrSourceCode[ iCurrLineIndex ] = new char[ MAX_SOURCE_LINE_SIZE+1 ];
if( !g_ppstrSourceCode[ iCurrLineIndex ] )
ExitOnError( "沒有足夠的空間非配給代碼行緩存" );
// 讀取代碼行
char *p = fgets( g_ppstrSourceCode[ iCurrLineIndex ], MAX_SOURCE_LINE_SIZE, g_pSourceFile );
// 處理末尾沒有字符的情況
if( p == 0 )
g_ppstrSourceCode[ iCurrLineIndex ][ 0 ] = '\0';
// 去除注釋和左右空格
StripComments( g_ppstrSourceCode[ iCurrLineIndex ] );
TrimWhitespace( g_ppstrSourceCode[ iCurrLineIndex ] );
// 確保去除空格和去除注釋后的代碼行后面有換行符
size_t iCodeLineLength = strlen( g_ppstrSourceCode[ iCurrLineIndex ] );
if( g_ppstrSourceCode[ iCurrLineIndex ] [ iCodeLineLength-1 ] != '\n' )
{
g_ppstrSourceCode[ iCurrLineIndex ] [ iCodeLineLength ] = '\n';
g_ppstrSourceCode[ iCurrLineIndex ] [ iCodeLineLength+1 ] = '\0';
}
// test
// printf( g_ppstrSourceCode[ iCurrLineIndex ] );
}
// 關閉 ASCII 方式打開的源文件
fclose( g_pSourceFile );
}
/*****************************************************************************************
*
* AssembleSourceFile()
*
* 匯編源代碼
*/
void AssembleSourceFile()
{
// 初始化腳本頭
g_ScriptHeader.iStackSize = 0;
g_ScriptHeader.iGlobalDataSize = 0;
g_ScriptHeader.iIsMainFuncPresent = false;
// 設置一些初始變量
g_iInstrStreamSize = 0;
g_bIsSetStackSizeFound = false;
// 設置當前函數的標志和變量
bool bIsFuncActive = false;
FuncNode* pCurrFunc;
int iCurrFuncIndex = 0;
int iCurrFuncParamCount = 0;
int iCurrFuncLocalDataSize = 0;
char pstrCurrFuncName[ MAX_IDENT_SIZE ];
// 用于處理指令時保存指令
InstrLookup CurrInstr;
// ---- 第一遍掃描
// 重置詞法分析器
ResetLexer();
// 遍歷每一行代碼
while( true )
{
// 檢測是否到達代碼結尾
if( GetNextToken() == END_OF_TOKEN_STREAM )
break;
// 處理Token
switch( g_Lexer.CurrToken )
{
// ---- 指示符
// SetStackSize
case TOKEN_TYPE_SETSTACKSIZE:
// SetStackSize 只能出現在全局范圍內
if( bIsFuncActive )
ExitOnCodeError( ERROR_MSG_LOCAL_SETSTACKSIZE );
// SetStackSize 只能出現一次
if( g_bIsSetStackSizeFound == true )
ExitOnCodeError( ERROR_MSG_MULTIPLE_SETSTACKSIZE );
// 讀取下一個單詞,它應該包含堆棧大小
if( GetNextToken() != TOKEN_TYPE_INT )
ExitOnCodeError( ERROR_MSG_INVALID_STACK_SIZE );
// 把這個單詞從字符串的表示轉換成一個整數值,并存儲在腳本頭中
g_ScriptHeader.iStackSize = atoi( GetCurrLexeme() );
// 設置 SetStackSize 標志已經找到
g_bIsSetStackSizeFound = true;
break;
// Func
case TOKEN_TYPE_FUNC:
{
// 檢測 Func 標簽是否是出現在了函數內部
if( bIsFuncActive )
ExitOnCodeError( ERROR_MSG_NESTED_FUNC );
// 取下一個單詞,即函數名
if( GetNextToken() != TOKEN_TYPE_IDENT )
ExitOnCodeError( ERROR_MSG_IDENT_EXPECTED );
char *pstrFuncName = GetCurrLexeme();
// 計算函數入口點,即直接跟在當前指令后面的指令
// 也就相當于指令流的大小
int iEntryPoint = g_iInstrStreamSize;
// 把這個函數添加到函數表中,如果已經聲明過了
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -