📄 xasm.cpp
字号:
OP_FLAG_TYPE_FLOAT |
OP_FLAG_TYPE_STRING |
OP_FLAG_TYPE_MEM_REF |
OP_FLAG_TYPE_REG );
// Pop Destination
iInstrIndex = AddInstrLookup ( "Pop", INSTR_POP, 1 );
SetOpType ( iInstrIndex, 0, OP_FLAG_TYPE_MEM_REF |
OP_FLAG_TYPE_REG );
// ---- The Function Interface
// 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 );
// ---- Miscellaneous
// 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 ()
*
* Adds an instruction to the instruction lookup table.
*/
int AddInstrLookup ( char * pstrMnemonic, int iOpcode, int iOpCount )
{
// Just use a simple static int to keep track of the next instruction index in the
// table.
static int iInstrIndex = 0;
// Make sure we haven't run out of instruction indices
if ( iInstrIndex >= MAX_INSTR_LOOKUP_COUNT )
return -1;
// Set the mnemonic, opcode and operand count fields
strcpy ( g_InstrTable [ iInstrIndex ].pstrMnemonic, pstrMnemonic );
strupr ( g_InstrTable [ iInstrIndex ].pstrMnemonic );
g_InstrTable [ iInstrIndex ].iOpcode = iOpcode;
g_InstrTable [ iInstrIndex ].iOpCount = iOpCount;
// Allocate space for the operand list
g_InstrTable [ iInstrIndex ].OpList = ( OpTypes * ) malloc ( iOpCount * sizeof ( OpTypes ) );
// Copy the instruction index into another variable so it can be returned to the caller
int iReturnInstrIndex = iInstrIndex;
// Increment the index for the next instruction
++ iInstrIndex;
// Return the used index to the caller
return iReturnInstrIndex;
}
/******************************************************************************************
*
* AddString ()
*
* Adds a string to a linked list, blocking duplicate entries
*/
int AddString ( LinkedList * pList, char * pstrString )
{
// ---- First check to see if the string is already in the list
// Create a node to traverse the list
LinkedListNode * pNode = pList->pHead;
// Loop through each node in the list
for ( int iCurrNode = 0; iCurrNode < pList->iNodeCount; ++ iCurrNode )
{
// If the current node's string equals the specified string, return its index
if ( strcmp ( ( char * ) pNode->pData, pstrString ) == 0 )
return iCurrNode;
// Otherwise move along to the next node
pNode = pNode->pNext;
}
// ---- Add the new string, since it wasn't added
// Create space on the heap for the specified string
char * pstrStringNode = ( char * ) malloc ( strlen ( pstrString ) + 1 );
strcpy ( pstrStringNode, pstrString );
// Add the string to the list and return its index
return AddNode ( pList, pstrStringNode );
}
/******************************************************************************************
*
* SetOpType ()
*
* Sets the operand type for the specified operand in the specified instruction.
*/
void SetOpType ( int iInstrIndex, int iOpIndex, OpTypes iOpType )
{
g_InstrTable [ iInstrIndex ].OpList [ iOpIndex ] = iOpType;
}
/******************************************************************************************
*
* Init ()
*
* Initializes the assembler.
*/
void Init ()
{
// Initialize the master instruction lookup table
InitInstrTable ();
// Initialize tables
InitLinkedList ( & g_SymbolTable );
InitLinkedList ( & g_LabelTable );
InitLinkedList ( & g_FuncTable );
InitLinkedList ( & g_StringTable );
InitLinkedList ( & g_HostAPICallTable );
}
/******************************************************************************************
*
* ShutDown ()
*
* Frees any dynamically allocated resources back to the system.
*/
void ShutDown ()
{
// ---- Free source code array
// Free each source line individually
for ( int iCurrLineIndex = 0; iCurrLineIndex < g_iSourceCodeSize; ++ iCurrLineIndex )
free ( g_ppstrSourceCode [ iCurrLineIndex ] );
// Now free the base pointer
free ( g_ppstrSourceCode );
// ---- Free the assembled instruction stream
if ( g_pInstrStream )
{
// Free each instruction's operand list
for ( int iCurrInstrIndex = 0; iCurrInstrIndex < g_iInstrStreamSize; ++ iCurrInstrIndex )
if ( g_pInstrStream [ iCurrInstrIndex ].pOpList )
free ( g_pInstrStream [ iCurrInstrIndex ].pOpList );
// Now free the stream itself
free ( g_pInstrStream );
}
// ---- Free the tables
FreeLinkedList ( & g_SymbolTable );
FreeLinkedList ( & g_LabelTable );
FreeLinkedList ( & g_FuncTable );
FreeLinkedList ( & g_StringTable );
FreeLinkedList ( & g_HostAPICallTable );
}
/******************************************************************************************
*
* ResetLexer ()
*
* Resets the lexer to the beginning of the source file by setting the current line and
* indices to zero.
*/
void ResetLexer ()
{
// Set the current line to the start of the file
g_Lexer.iCurrSourceLine = 0;
// Set both indices to point to the start of the string
g_Lexer.iIndex0 = 0;
g_Lexer.iIndex1 = 0;
// Set the token type to invalid, since a token hasn't been read yet
g_Lexer.CurrToken = TOKEN_TYPE_INVALID;
// Set the lexing state to no strings
g_Lexer.iCurrLexState = LEX_STATE_NO_STRING;
}
/******************************************************************************************
*
* GetNextToken ()
*
* Extracts and returns the next token from the character stream. Also makes a copy of
* the current lexeme for use with GetCurrLexeme ().
*/
Token GetNextToken ()
{
// ---- Lexeme Extraction
// Move the first index (Index0) past the end of the last token, which is marked
// by the second index (Index1).
g_Lexer.iIndex0 = g_Lexer.iIndex1;
// Make sure we aren't past the end of the current line. If a string is 8 characters long,
// it's indexed from 0 to 7; therefore, indices 8 and beyond lie outside of the string and
// require us to move to the next line. This is why I use >= for the comparison rather
// than >. The value returned by strlen () is always one greater than the last valid
// character index.
if ( g_Lexer.iIndex0 >= strlen ( g_ppstrSourceCode [ g_Lexer.iCurrSourceLine ] ) )
{
// If so, skip to the next line but make sure we don't go past the end of the file.
// SkipToNextLine () will return FALSE if we hit the end of the file, which is
// the end of the token stream.
if ( ! SkipToNextLine () )
return END_OF_TOKEN_STREAM;
}
// If we just ended a string, tell the lexer to stop lexing
// strings and return to the normal state
if ( g_Lexer.iCurrLexState == LEX_STATE_END_STRING )
g_Lexer.iCurrLexState = LEX_STATE_NO_STRING;
// Scan through the potential whitespace preceding the next lexeme, but ONLY if we're
// not currently parsing a string lexeme (since strings can contain arbitrary whitespace
// which must be preserved).
if ( g_Lexer.iCurrLexState != LEX_STATE_IN_STRING )
{
// Scan through the whitespace and check for the end of the line
while ( TRUE )
{
// If the current character is not whitespace, exit the loop because the lexeme
// is starting.
if ( ! IsCharWhitespace ( g_ppstrSourceCode [ g_Lexer.iCurrSourceLine ][ g_Lexer.iIndex0 ] ) )
break;
// It is whitespace, however, so move to the next character and continue scanning
++ g_Lexer.iIndex0;
}
}
// Bring the second index (Index1) to the lexeme's starting character, which is marked by
// the first index (Index0)
g_Lexer.iIndex1 = g_Lexer.iIndex0;
// Scan through the lexeme until a delimiter is hit, incrementing Index1 each time
while ( TRUE )
{
// Are we currently scanning through a string?
if ( g_Lexer.iCurrLexState == LEX_STATE_IN_STRING )
{
// If we're at the end of the line, return an invalid token since the string has no
// ending double-quote on the line
if ( g_Lexer.iIndex1 >= strlen ( g_ppstrSourceCode [ g_Lexer.iCurrSourceLine ] ) )
{
g_Lexer.CurrToken = TOKEN_TYPE_INVALID;
return g_Lexer.CurrToken;
}
// If the current character is a backslash, move ahead two characters to skip the
// escape sequence and jump to the next iteration of the loop
if ( g_ppstrSourceCode [ g_Lexer.iCurrSourceLine ][ g_Lexer.iIndex1 ] == '\\' )
{
g_Lexer.iIndex1 += 2;
continue;
}
// If the current character isn't a double-quote, move to the next, otherwise exit
// the loop, because the string has ended.
if ( g_ppstrSourceCode [ g_Lexer.iCurrSourceLine ][ g_Lexer.iIndex1 ] == '"' )
break;
++ g_Lexer.iIndex1;
}
// We are not currently scanning through a string
else
{
// If we're at the end of the line, the lexeme has ended so exit the loop
if ( g_Lexer.iIndex1 >= st
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -