一直难以净下心来好好完成一件事,彷徨了许久,最终觉得一个程序开发者的修养在于根基的牢固。
对游戏脚本有些兴趣,而且可以加深自己在语言方面的能力,所以开始研究学习脚本语言的实现,学习用书是游戏《脚本高级编程》,争取将书中所讲亲自实现一遍。
之前所有至 9.12.2008
写汇编器用到的数据结构
字符串表、符号表、函数表、标签表、指令查找表、主应用程序API调用表。
写字符处理功能函数
包括标识符检测等
更改了注释习惯
/*
文件
DataStructs.h
内容
汇编器用到的数据结构定义与对应的功能函数
日期
12.9.2008
作者
张锦
*/
#ifndef _DATASTRUCTS_H_
#define _DATASTRUCTS_H_
// ---- 宏 -----------------------------------------------------------------------------------
// ---- 源代码与标识符 -------------------------------------------------------------------
#define MAX_IDENT_SIZE 100 // 标识符最大长度
#define MAX_SOURCE_LINE_SIZE 4096 // 源代码最大函数
// ---- 指令查找表 -----------------------------------------------------------------------
#define MAX_INSTR_MNEMONIC_SIZE 16 // 指令助记符字符串的最大长度
#define MAX_INSTR_LOOKUP_COUNT 256 // 指令查找表存储的指令的最大个数
// ---- 操作数类型位域掩码 -----------------------------------------------------------
#define OP_FLAG_TYPE_INT 1 // 整形字面值
#define OP_FLAG_TYPE_FLOAT 2 // 浮点型字面值
#define OP_FLAG_TYPE_STRING 4 // 字符串型字面值
#define OP_FLAG_TYPE_MEM_REF 8 // 内存引用
#define OP_FLAG_TYPE_LINE_LABEL 16 // 行标签
#define OP_FLAG_TYPE_FUNC_NAME 32 // 函数名(用于call指令)
#define OP_FLAG_TYPE_REG 128 // 一个寄存器,即_RetVal
#define OP_FLAG_TYPE_HOST_API_CALL 64 // 主应用程序API调用(用于CallHost指令中)
// ---- 数据结构 -----------------------------------------------------------------------------
// ---- 汇编指令流 -----------------------------------------------------------------------
struct Op
{
int iType; // 类型
union
{
int iIntLiteral; // 整形字面量
float fFloatLiteral; // 浮点型字面量
int iStringTableIndex; // 字符串表索引
int iStackIndex; // 堆栈索引
int iInstrIndex; // 指令索引
int iFuncIndex; // 函数索引
int iHostAPICallIndex; // 主应用程序API调用索引
int iReg; // 寄存器码
};
int iOffsetIndex; // 偏移量索引
};
struct Instr
{
int iOpcode; // 操作码
int iOpCount; // 操作数
Op *pOpList; // 指向操作数列表的指针
};
// ---- 脚本头 ---------------------------------------------------------------------------
struct ScriptHeader
{
int iStackSize; // 要求的堆栈大小
int iGlobalDataSize; // 脚本中全局数据的大小
int iIsMainFuncPresent; // _Main () 是否存在
int iMainFuncIndex; // _Main () 函数的索引
};
// ---- 简单链表 -------------------------------------------------------------------------
struct LinkedListNode
{
void *pData; // 指向节点数据的指针
LinkedListNode *pNext; // 指向链表中下一个节点的指针
};
struct LinkedList
{
LinkedListNode *pHead; // 指向链表头节点的指针
LinkedListNode *pTail; // 指向链表末节点的指针
int iNodeCount; // 连表中节点的数量
};
// ---- 函数表 ---------------------------------------------------------------------------
struct FuncNode
{
int iIndex; // 索引
char pstrName[MAX_IDENT_SIZE]; // 名称
int iEntryPoint; // 入口点
int iParamCount; // 参数个数
int iLocalDataSize; // 局部数据大小
};
// ---- 符号表 ---------------------------------------------------------------------------
struct SymbolNode
{
int iIndex; // 索引
char pstrIdent[MAX_IDENT_SIZE]; // 标识符
int iSize; // 大小
int iStackIndex; // 负号指向的堆栈索引
int iFuncIndex; // 负号所在的函数
};
// ---- 标签表 ---------------------------------------------------------------------------
struct LabelNode
{
int iIndex; // 标签表节点
int iTargetIndex; // 目标指令索引
int iFuncIndex; // 标签所属函数
char pstrIdent[MAX_IDENT_SIZE]; // 标识符
};
// ---- 指令查找表 -----------------------------------------------------------------------
typedef int OpTypes;
struct InstrLookup
{
char pstrMnemonic[MAX_INSTR_MNEMONIC_SIZE]; // 助记符
int iOpcode; // 操作码
int iOpCount; // 操作数个数
OpTypes *OpList; // 操作数类型列表指针
};
// ---- 全局变量 -----------------------------------------------------------------------------
// ---- 源代码缓存与计数 -----------------------------------------------------------------
char **g_ppstrSourceCode = 0;
int g_iSourceCodeSize = 0;
// ---- 指令缓存与计数 -------------------------------------------------------------------
Instr *g_pInstrStream = 0;
int g_iInstrStreamSize = 0;
// ---- 字符串表 -------------------------------------------------------------------------
LinkedList g_StringTable;
// ---- 函数表 ---------------------------------------------------------------------------
LinkedList g_FuncTable;
// ---- 标签表 ---------------------------------------------------------------------------
LinkedList g_LabelTable;
// ---- 符号表 ---------------------------------------------------------------------------
LinkedList g_SymbolTable;
// ---- 指令查找表 -----------------------------------------------------------------------
InstrLookup g_InstrTable[MAX_INSTR_LOOKUP_COUNT];
// ---- 主程序API调用表
LinkedList g_HostAPICallTable;
// ---- 函数原型 -----------------------------------------------------------------------------
// ---- 简单链表 -------------------------------------------------------------------------
int AddFunc( char *pstrName, int iEntryPoint );
void InitLinkedList( LinkedList *pList );
void FreeLinkedList( LinkedList *pList );
// ---- 字符串表 -------------------------------------------------------------------------
int AddString( LinkedList *pList, char *pstrString );
// ---- 函数表 ---------------------------------------------------------------------------
int AddFunc( char * pstrName, int iEntryPoint );
void SetFuncInfo( char * pstrName, int iParamCount, int iLocalDataSize );
FuncNode* GetFuncByName( char *pstrName );
// ---- 符号表 ---------------------------------------------------------------------------
int AddSymbol( char *pstrIdent, int iSize, int iStackIndex, int iFuncIndex );
int GetSizeByIdent( char *pstrIdent, int iFuncIndex );
int GetStackIndexByIdent( char *pstrIdent, int iFuncIndex );
SymbolNode* GetSymbolByIdent( char *pstrIdent, int iFuncIndex );
// ---- 标签表 ---------------------------------------------------------------------------
int AddLabel( char *pstrIdent, int iTargetIndex, int iFuncIndex );
LabelNode* GetLabelByIdent( char *pstrIdent, int iFuncIndex );
// ---- 指令查找表 -----------------------------------------------------------------------
int AddInstrLookup( char *pstrMnemonic, int iOpCode, int iOpCount );
void SetOpType( int iInstrIndex, int iOpIndex, OpTypes iOpType );
// ---- 函数定义 -----------------------------------------------------------------------------
/*****************************************************************************************
*
* AddNode()
*
* 向指定的简单链表链表添加节点
*/
int AddNode( LinkedList *pList, void *pData )
{
// 创建一个新节点
LinkedListNode *pNewNode = new LinkedListNode;
// 把节点数据设定成指定的指针
pNewNode->pData = pData;
// 把下一个指针设为空
pNewNode->pNext = 0;
// 如果当前链表为空,则把头指针和末指针都设成新节点
if( pList->iNodeCount == 0 )
{
pList->pHead = pList->pTail = pNewNode;
}
// 否则把它追加到链表的最后
else
{
pList->pTail->pNext = pNewNode;
pList->pTail = pNewNode;
}
// 增大链表中节点的数量
++pList->iNodeCount;
// 返回新的链表的大小减一,也就是新节点的索引
return pList->iNodeCount - 1;
}
/*****************************************************************************************
*
* InitLinkedList()
*
* 初始化指定链表
*/
void InitLinkedList( LinkedList *pList )
{
pList->pHead = 0;
pList->pTail = 0;
pList->iNodeCount = 0;
}
/*****************************************************************************************
*
* FreeLinkedList()
*
* 释放指定链表
*/
void FreeLinkedList( LinkedList *pList )
{
if( !pList ) return;
if( pList->iNodeCount != 0 )
{
// 保存当前节点和下一个节点的指针
LinkedListNode *pCurrNode;
LinkedListNode *pNextNode;
// 设定当前节点为链表头
pCurrNode = pList->pHead;
// 遍历链表
while(true)
{
// 释放当前节点前保存下一个节点的指针
pNextNode = pCurrNode->pNext;
// 释放当前节点中的数据
if( pCurrNode->pData != 0 )
{
delete pCurrNode->pData;
}
// 清除当前节点
delete pCurrNode;
// 如果存在下一个节点则后移,否则退出循环
if( pNextNode != 0 )
{
pCurrNode = pNextNode;
}
else
{
break;
}
}
}
}
/*****************************************************************************************
*
* AddString()
*
* 向指定的表添加字符串
*/
int AddString( LinkedList *pList, char *pstrString )
{
// 创建节点指针用于遍历
LinkedListNode *pNode = pList->pHead;
// 对表中的每一个节点循环操作
for( int iCurrNode = 0 ; iCurrNode<pList->iNodeCount ; ++ iCurrNode )
{
if( strcmp( pstrString, (char*)pNode->pData ) == 0 )
{
return iCurrNode;
}
else
{
pNode = pNode->pNext;
}
}
// 字符串还没有添加,则添加新的字符串
char *pstrStringNode = new char[strlen(pstrString)+1];
strcpy( pstrStringNode, pstrString );
return AddNode( pList, pstrStringNode );
}
/*****************************************************************************************
*
* AddFunc()
*
* 向函数表添加函数
*/
int AddFunc( char *pstrName, int iEntryPoint )
{
// 如果指定函数名已经存在,则返回一个无效索引
if( GetFuncByName( pstrName ) != 0 )
return -1;
// 创建一个函数节点
FuncNode *pNewFunc = new FuncNode;
pNewFunc->iEntryPoint = iEntryPoint;
strcpy( pNewFunc->pstrName, pstrName );
// 把函数节点添加到表中并取回索引
pNewFunc->iIndex = AddNode( &g_FuncTable, pNewFunc );
// 返回新函数的索引
return pNewFunc->iIndex;
}
/*****************************************************************************************
*
* SetFuncInfo()
*
* 设置函数表节点参数数量、局部数据大小
*/
void SetFuncInfo( char *pstrName, int iParamCount, int iLocalDataSize )
{
// 在函数表中查找指定函数
FuncNode *pFunc = GetFuncByName( pstrName );
// 设定其余信息
pFunc->iParamCount = iParamCount;
pFunc->iLocalDataSize = iLocalDataSize;
}
/*****************************************************************************************
*
* GetFuncByName()
*
* 根据函数名取得函数节点
*/
FuncNode* GetFuncByName( char *pstrName )
{
// 如果表是空的,则返回一个空指针
if( g_FuncTable.iNodeCount == 0 )
return 0;
// 创建一个指针用于链表的遍历
LinkedListNode *pCurrNode = g_FuncTable.pHead;
// 遍历链表直至找到匹配的结构
for( int iCurrNode = 0 ; iCurrNode < g_FuncTable.iNodeCount ; ++ iCurrNode )
{
// 将当前节点数据转换为函数表指针
FuncNode *pCurrFunc = (FuncNode*)pCurrNode->pData;
// 检测是否匹配
if( strcmp( pCurrFunc->pstrName, pstrName ) == 0 )
{
return pCurrFunc;
}
else
{
pCurrNode = pCurrNode->pNext;
}
}
// 没有找到匹配的结构,返回0
return 0;
}
/*****************************************************************************************
*
* AddSymbol()
*
* 向符号表添加符号
*/
int AddSymbol( char *pstrIdent, int iSize, int iStackIndex, int iFuncIndex )
{
// 如果标签已经存在,返回无效索引
if( GetSymbolByIdent( pstrIdent, iFuncIndex ) )
return -1;
// 创建新的符号节点
SymbolNode *pNewSymbol = new SymbolNode;
// 为新节点赋值
strcpy( pNewSymbol->pstrIdent, pstrIdent );
pNewSymbol->iSize = iSize;
pNewSymbol->iStackIndex = iStackIndex;
pNewSymbol->iFuncIndex = iFuncIndex;
// 想符号表中添加符号,并取得索引
pNewSymbol->iIndex = AddNode( &g_SymbolTable, pNewSymbol );
// 返回新符号的索引
return pNewSymbol->iIndex;
}
/*****************************************************************************************
*
* GetSymbolByIdent()
*
* 根据标识符取得符号节点指针
*/
SymbolNode* GetSymbolByIdent( char *pstrIdent, int iFuncIndex )
{
// 声明链表节点指针用于符号表的遍历
LinkedListNode *pCurrNode = g_SymbolTable.pHead;
// 遍历符号表
for( int iCurrNode=0 ; iCurrNode<g_SymbolTable.iNodeCount ; ++ iCurrNode )
{
// 将当前节点数据转换成符号表节点数据
SymbolNode *pCurrSymbol = (SymbolNode*)pCurrNode->pData;
// 检测当前符号节点是否和指定符号匹配
if( strcmp( pCurrSymbol->pstrIdent, pstrIdent ) == 0 )
{
// 当前节点标识符匹配时检测作用域是否相同或重叠(全局/局部)
if( pCurrSymbol->iFuncIndex == iFuncIndex || pCurrSymbol->iStackIndex >= 0 )
{
return pCurrSymbol;
}
}
else
{
pCurrNode = pCurrNode->pNext;
}
}
// 没找到指定节点,返回0
return 0;
}
/*****************************************************************************************
*
* GetStackIndexByIdent()
*
* 根据标识符取得其堆栈索引
*/
int GetStackIndexByIdent( char *pstrIdent, int iFuncIndex )
{
// 取得符号
SymbolNode *pSymbol = GetSymbolByIdent( pstrIdent, iFuncIndex );
// 返回堆栈索引
return pSymbol->iStackIndex;
}
/*****************************************************************************************
*
* GetSizeByIdent()
*
* 根据标识符取得符号大小
*/
int GetSizeByIdent( char *pstrIdent, int iFuncIndex )
{
// 取得符号
SymbolNode *pSymbol = GetSymbolByIdent( pstrIdent, iFuncIndex );
// 返回符号大小
return pSymbol->iSize;
}
/*****************************************************************************************
*
* AddLabel()
*
* 向标签表添加标签
*/
int AddLabel( char *pstrIdent, int iTargetIndex, int iFuncIndex )
{
// 如果标签已经存在,则返回无效索引-1
if( GetLabelByIdent( pstrIdent, iFuncIndex ) )
return -1;
// 创建新标签节点
LabelNode *pNewLabel = new LabelNode;
// 为新节点赋值
strcpy( pNewLabel->pstrIdent, pstrIdent );
pNewLabel->iTargetIndex = iTargetIndex;
pNewLabel->iFuncIndex = iFuncIndex;
// 将新节点插入到标签表并取得索引
pNewLabel->iIndex = AddNode( &g_LabelTable, pNewLabel );
// 返回索引
return pNewLabel->iIndex;
}
/*****************************************************************************************
*
* GetLabelByIdent()
*
* 根据标标签标识符取得标签节点
*/
LabelNode* GetLabelByIdent( char *pstrIdent, int iFuncIndex )
{
// 如果标签表为空,返回0
if( g_LabelTable.iNodeCount == 0 )
return 0;
// 创建一个链表节点用于遍历
LinkedListNode *pCurrNode = g_LabelTable.pHead;
// 遍历标签表,寻找匹配的标签
for( int i=0 ; i<g_LabelTable.iNodeCount ; ++i )
{
LabelNode *pCurrLabel = (LabelNode*)pCurrNode->pData;
// 如果名称和范围匹配,则返回当前指针
if( strcmp( pCurrLabel->pstrIdent, pstrIdent) == 0 &&
pCurrLabel->iFuncIndex == iFuncIndex )
{
return pCurrLabel;
}
else
{
pCurrNode = pCurrNode->pNext;
}
}
// 没有找到匹配的结构,返回0
return 0;
}
/*****************************************************************************************
*
* 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;
}
#endif _DATASTRUCTS_H_
2719

被折叠的 条评论
为什么被折叠?



