beebasm
changeset 5:bf4ee211ca83
BeebASM v0.03 - first released Jan 07 2008 09:14:08
| author | Samwise <samwise@bagshot-row.org> |
|---|---|
| date | Sun May 02 12:04:21 2010 +0100 |
| parents | 03efcda85f5e |
| children | 72e5df92f741 |
| files | about.txt beebasm.exe demo.asm demo.ssd src/Makefile src/Makefile.inc src/asmexception.h src/assemble.cpp src/commands.cpp src/expression.cpp src/lineparser.h src/main.cpp src/objectcode.cpp src/objectcode.h src/sourcefile.cpp src/sourcefile.h src/symboltable.cpp src/symboltable.h |
| diffstat | 18 files changed, 518 insertions(+), 30 deletions(-) [+] |
line diff
1.1 --- a/about.txt Sun May 02 11:57:59 2010 +0100 1.2 +++ b/about.txt Sun May 02 12:04:21 2010 +0100 1.3 @@ -1,6 +1,6 @@ 1.4 ******************************************************************************* 1.5 * * 1.6 -* BeebAsm * 1.7 +* BeebAsm V0.04 * 1.8 * * 1.9 * A portable 6502 assembler with BBC Micro style syntax * 1.10 * * 1.11 @@ -154,6 +154,10 @@ 1.12 1.13 Verbose output. Assembled code will be output to the screen. 1.14 1.15 +-d 1.16 + 1.17 +Dumps all symbols in Swift-compatible format after assembly 1.18 + 1.19 1.20 1.21 1.22 @@ -210,6 +214,10 @@ 1.23 SGN(val) Return -1, 0 or 1, depending on the sign of the argument 1.24 RND(val) RND(1) returns a random number between 0 and 1 1.25 RND(n) returns an integer between 0 and n-1 1.26 +NOT(val) Return the bitwise 1's complement of val 1.27 +LOG(val) Return the base 10 log of val 1.28 +LN(val) Return the natural log of val 1.29 +EXP(val) Return e raised to the power of val 1.30 1.31 Also, some constants are defined: 1.32 1.33 @@ -247,6 +255,12 @@ 1.34 reserve a space of a fixed size in the code. 1.35 1.36 1.37 +SKIPTO <addr> 1.38 + 1.39 +Moves the address pointer to the specified address. An error is generated if 1.40 +this address is behind the current address pointer. 1.41 + 1.42 + 1.43 ALIGN <alignment> 1.44 1.45 Used to align the address pointer to the next boundary, e.g. use ALIGN &100 to 1.46 @@ -259,6 +273,11 @@ 1.47 Includes the specified source file in the code at this point. 1.48 1.49 1.50 +INCBIN "filename" 1.51 + 1.52 +Includes the specified binary file in the object code at this point. 1.53 + 1.54 + 1.55 EQUB a [, b, c, ...] 1.56 1.57 Insert the specified byte(s) into the code. Note, unlike BBC BASIC, that a 1.58 @@ -369,6 +388,39 @@ 1.59 IF debugraster:LDA #3:STA &FE21:ENDIF 1.60 1.61 1.62 +{ ... } 1.63 + 1.64 +Curly braces can be used to specify a block of code in which all symbols and 1.65 +labels defined will exist only within this block. Effectively, this is a 1.66 +mechanism for providing 'local labels' without the slightly cumbersome syntax 1.67 +demanded by some other assemblers. These can be nested. Any symbols defined 1.68 +within a block will override any of the same name outside of the block, exactly 1.69 +like C/C++ - not sure if I like this behaviour, but for now it will stay. 1.70 + 1.71 +Example of use: 1.72 + 1.73 + .initialise 1.74 + { 1.75 + LDY #31 1.76 + LDA #0 1.77 + .loop ; label visible only within the braces 1.78 + STA buffer,Y 1.79 + DEY 1.80 + BPL loop 1.81 + RTS 1.82 + } 1.83 + 1.84 + .copy 1.85 + { 1.86 + LDY #31 1.87 + .loop ; perfectly ok to define .loop again in a new block 1.88 + LDA source,Y 1.89 + STA dest,Y 1.90 + DEY 1.91 + BPL loop 1.92 + RTS 1.93 + } 1.94 + 1.95 1.96 1.97 7. TIPS AND TRICKS 1.98 @@ -471,6 +523,11 @@ 1.99 1.100 9. VERSION HISTORY 1.101 1.102 +06/01/2008 0.04 Added braces for scoping labels. Added INCBIN, SKIPTO. 1.103 + Added some missing functions (NOT, LOG, LN, EXP). 1.104 + Tightened up error checking on assembling out of range 1.105 + addresses (negative, or greater than &FFFF). 1.106 +05/01/2008 0.03 Added symbol dump for use with Swift. 1.107 20/12/2007 0.02 Fixed small bug which withheld filename and line number 1.108 display in error messages. 1.109 16/12/2007 0.01 First released version.
2.1 Binary file beebasm.exe has changed
3.1 --- a/demo.asm Sun May 02 11:57:59 2010 +0100 3.2 +++ b/demo.asm Sun May 02 12:04:21 2010 +0100 3.3 @@ -54,7 +54,6 @@ 3.4 3.5 ORG &1100 3.6 3.7 - 3.8 \ ****************************************************************** 3.9 \ * The entry point of the demo 3.10 \ ****************************************************************** 3.11 @@ -476,3 +475,4 @@ 3.12 \ ****************************************************************** 3.13 3.14 SAVE "Code", start, end 3.15 +
4.1 Binary file demo.ssd has changed
5.1 --- a/src/Makefile Sun May 02 11:57:59 2010 +0100 5.2 +++ b/src/Makefile Sun May 02 12:04:21 2010 +0100 5.3 @@ -35,7 +35,7 @@ 5.4 5.5 # Parameters to the executable 5.6 5.7 -PARAMS := -i ..\demo.asm -do ..\demo.ssd -boot Code 5.8 +PARAMS := -i ..\demo.asm -do ..\demo.ssd -boot Code -d 5.9 5.10 5.11
6.1 --- a/src/Makefile.inc Sun May 02 11:57:59 2010 +0100 6.2 +++ b/src/Makefile.inc Sun May 02 12:04:21 2010 +0100 6.3 @@ -21,7 +21,7 @@ 6.4 # CPUS The number of CPUs on this machine 6.5 # VERBOSE Echoes all commands launched by make 6.6 # 6.7 -# @author camrtw 6.8 +# @author RTW 6.9 # 6.10 #************************************************************************************************** 6.11 6.12 @@ -57,9 +57,9 @@ 6.13 CC := C:/MinGW/bin/gcc 6.14 CXX := C:/MinGW/bin/gcc 6.15 LD := C:/MinGW/bin/gcc 6.16 -MKDIR := C:/Cygwin/bin/mkdir -p 6.17 -RM := C:/Cygwin/bin/rm -f 6.18 -ECHO := @@C:/Cygwin/bin/echo -e 6.19 +MKDIR := C:/Utilities/mkdir -p 6.20 +RM := C:/Utilities/rm -f 6.21 +ECHO := @@C:/Utilities/echo -e 6.22 6.23 6.24 # Declare default number of CPUs
7.1 --- a/src/asmexception.h Sun May 02 11:57:59 2010 +0100 7.2 +++ b/src/asmexception.h Sun May 02 12:04:21 2010 +0100 7.3 @@ -175,6 +175,7 @@ 7.4 DEFINE_SYNTAX_EXCEPTION( BranchOutOfRange, "Branch out of range." ); 7.5 DEFINE_SYNTAX_EXCEPTION( NoAbsolute, "Absolute addressing mode not allowed for this instruction." ); 7.6 DEFINE_SYNTAX_EXCEPTION( BadAbsolute, "Syntax error in absolute instruction." ); 7.7 +DEFINE_SYNTAX_EXCEPTION( BadAddress, "Out of range address." ); 7.8 DEFINE_SYNTAX_EXCEPTION( BadIndexed, "Syntax error in indexed instruction." ); 7.9 DEFINE_SYNTAX_EXCEPTION( NoIndexedX, "X indexed mode does not exist for this instruction." ); 7.10 DEFINE_SYNTAX_EXCEPTION( NoIndexedY, "Y indexed mode does not exist for this instruction." ); 7.11 @@ -186,14 +187,16 @@ 7.12 DEFINE_SYNTAX_EXCEPTION( NextWithoutFor, "NEXT without FOR." ); 7.13 DEFINE_SYNTAX_EXCEPTION( ForWithoutNext, "FOR without NEXT." ); 7.14 DEFINE_SYNTAX_EXCEPTION( BadStep, "Step value cannot be zero." ); 7.15 -DEFINE_SYNTAX_EXCEPTION( TooManyFORs, "Too many nested FORs." ); 7.16 -DEFINE_SYNTAX_EXCEPTION( CantInclude, "Cannot include a source file within a FOR loop." ); 7.17 +DEFINE_SYNTAX_EXCEPTION( TooManyFORs, "Too many nested FORs or braces." ); 7.18 +DEFINE_SYNTAX_EXCEPTION( MismatchedBraces, "Mismatched braces." ); 7.19 +DEFINE_SYNTAX_EXCEPTION( CantInclude, "Cannot include a source file within a FOR loop or braced block." ); 7.20 DEFINE_SYNTAX_EXCEPTION( ElseWithoutIf, "ELSE without IF." ); 7.21 DEFINE_SYNTAX_EXCEPTION( EndifWithoutIf, "ENDIF without IF." ); 7.22 DEFINE_SYNTAX_EXCEPTION( IfWithoutEndif, "IF without ENDIF." ); 7.23 DEFINE_SYNTAX_EXCEPTION( TooManyIFs, "Too many nested IFs." ); 7.24 DEFINE_SYNTAX_EXCEPTION( BadAlignment, "Bad alignment." ); 7.25 DEFINE_SYNTAX_EXCEPTION( OutOfRange, "Out of range." ); 7.26 +DEFINE_SYNTAX_EXCEPTION( BackwardsSkip, "Attempted to skip backwards to an address." ); 7.27 7.28 7.29 7.30 @@ -236,6 +239,7 @@ 7.31 DEFINE_ASSEMBLE_EXCEPTION( GuardHit, "Guard point hit." ); 7.32 DEFINE_ASSEMBLE_EXCEPTION( Overlap, "Trying to assemble over existing code." ); 7.33 DEFINE_ASSEMBLE_EXCEPTION( InconsistentCode, "Assembled object code has changed between 1st and 2nd pass. Has a zero-page symbol been forward-declared?" ); 7.34 - 7.35 +DEFINE_ASSEMBLE_EXCEPTION( FileOpen, "Error opening file." ); 7.36 +DEFINE_ASSEMBLE_EXCEPTION( FileRead, "Error reading file." ); 7.37 7.38 #endif // ASMEXCEPTION_H_
8.1 --- a/src/assemble.cpp Sun May 02 11:57:59 2010 +0100 8.2 +++ b/src/assemble.cpp Sun May 02 12:04:21 2010 +0100 8.3 @@ -528,6 +528,11 @@ 8.4 throw AsmException_SyntaxError_NotZeroPage( m_line, oldColumn + 1 ); 8.5 } 8.6 8.7 + if ( value < 0 ) 8.8 + { 8.9 + throw AsmException_SyntaxError_BadAddress( m_line, oldColumn + 1 ); 8.10 + } 8.11 + 8.12 Assemble2( instruction, INDY, value ); 8.13 return; 8.14 } 8.15 @@ -594,6 +599,11 @@ 8.16 throw AsmException_SyntaxError_NotZeroPage( m_line, oldColumn + 1 ); 8.17 } 8.18 8.19 + if ( value < 0 ) 8.20 + { 8.21 + throw AsmException_SyntaxError_BadAddress( m_line, oldColumn + 1 ); 8.22 + } 8.23 + 8.24 Assemble2( instruction, INDX, value ); 8.25 return; 8.26 } 8.27 @@ -656,6 +666,11 @@ 8.28 // we assemble abs or zp depending on whether 'value' is a 16- or 8-bit number. 8.29 // we contrive that unknown labels will get a 16-bit value so that absolute addressing is the default. 8.30 8.31 + if ( value < 0 || value > 0xFFFF ) 8.32 + { 8.33 + throw AsmException_SyntaxError_BadAddress( m_line, oldColumn ); 8.34 + } 8.35 + 8.36 if ( value < 0x100 && HasAddressingMode( instruction, ZP ) ) 8.37 { 8.38 Assemble2( instruction, ZP, value ); 8.39 @@ -698,6 +713,11 @@ 8.40 throw AsmException_SyntaxError_BadIndexed( m_line, m_column ); 8.41 } 8.42 8.43 + if ( value < 0 || value > 0xFFFF ) 8.44 + { 8.45 + throw AsmException_SyntaxError_BadAddress( m_line, oldColumn ); 8.46 + } 8.47 + 8.48 if ( value < 0x100 && HasAddressingMode( instruction, ZPX ) ) 8.49 { 8.50 Assemble2( instruction, ZPX, value ); 8.51 @@ -724,6 +744,11 @@ 8.52 throw AsmException_SyntaxError_BadIndexed( m_line, m_column ); 8.53 } 8.54 8.55 + if ( value < 0 || value > 0xFFFF ) 8.56 + { 8.57 + throw AsmException_SyntaxError_BadAddress( m_line, oldColumn ); 8.58 + } 8.59 + 8.60 if ( value < 0x100 && HasAddressingMode( instruction, ZPY ) ) 8.61 { 8.62 Assemble2( instruction, ZPY, value );
9.1 --- a/src/commands.cpp Sun May 02 11:57:59 2010 +0100 9.2 +++ b/src/commands.cpp Sun May 02 12:04:21 2010 +0100 9.3 @@ -43,7 +43,11 @@ 9.4 { "ALIGN", &LineParser::HandleAlign }, 9.5 { "SKIP", &LineParser::HandleSkip }, 9.6 { "GUARD", &LineParser::HandleGuard }, 9.7 - { "CLEAR", &LineParser::HandleClear } 9.8 + { "CLEAR", &LineParser::HandleClear }, 9.9 + { "SKIPTO", &LineParser::HandleSkipTo }, 9.10 + { "INCBIN", &LineParser::HandleIncBin }, 9.11 + { "{", &LineParser::HandleOpenBrace }, 9.12 + { "}", &LineParser::HandleCloseBrace } 9.13 }; 9.14 9.15 9.16 @@ -125,7 +129,7 @@ 9.17 } 9.18 else 9.19 { 9.20 - SymbolTable::Instance().AddSymbol( fullSymbolName, ObjectCode::Instance().GetPC() ); 9.21 + SymbolTable::Instance().AddSymbol( fullSymbolName, ObjectCode::Instance().GetPC(), true ); 9.22 } 9.23 } 9.24 else 9.25 @@ -341,6 +345,49 @@ 9.26 9.27 /*************************************************************************************************/ 9.28 /** 9.29 + LineParser::HandleSkipTo() 9.30 +*/ 9.31 +/*************************************************************************************************/ 9.32 +void LineParser::HandleSkipTo() 9.33 +{ 9.34 + int oldColumn = m_column; 9.35 + 9.36 + int addr = EvaluateExpressionAsInt(); 9.37 + if ( addr < 0 || addr > 0xFFFF ) 9.38 + { 9.39 + throw AsmException_SyntaxError_BadAddress( m_line, oldColumn ); 9.40 + } 9.41 + 9.42 + if ( ObjectCode::Instance().GetPC() > addr ) 9.43 + { 9.44 + throw AsmException_SyntaxError_BackwardsSkip( m_line, oldColumn ); 9.45 + } 9.46 + 9.47 + while ( ObjectCode::Instance().GetPC() < addr ) 9.48 + { 9.49 + try 9.50 + { 9.51 + ObjectCode::Instance().PutByte( 0 ); 9.52 + } 9.53 + catch ( AsmException_AssembleError& e ) 9.54 + { 9.55 + e.SetString( m_line ); 9.56 + e.SetColumn( m_column ); 9.57 + throw; 9.58 + } 9.59 + } 9.60 + 9.61 + if ( m_line[ m_column ] == ',' ) 9.62 + { 9.63 + // Unexpected comma (remembering that an expression can validly end with a comma) 9.64 + throw AsmException_SyntaxError_UnexpectedComma( m_line, m_column ); 9.65 + } 9.66 +} 9.67 + 9.68 + 9.69 + 9.70 +/*************************************************************************************************/ 9.71 +/** 9.72 LineParser::HandleInclude() 9.73 */ 9.74 /*************************************************************************************************/ 9.75 @@ -375,7 +422,7 @@ 9.76 9.77 if ( GlobalData::Instance().IsFirstPass() ) 9.78 { 9.79 - cout << "Including file " << filename << endl; 9.80 + cerr << "Including file " << filename << endl; 9.81 } 9.82 9.83 SourceFile input( filename.c_str() ); 9.84 @@ -394,6 +441,56 @@ 9.85 9.86 /*************************************************************************************************/ 9.87 /** 9.88 + LineParser::HandleIncBin() 9.89 +*/ 9.90 +/*************************************************************************************************/ 9.91 +void LineParser::HandleIncBin() 9.92 +{ 9.93 + if ( !AdvanceAndCheckEndOfStatement() ) 9.94 + { 9.95 + throw AsmException_SyntaxError_EmptyExpression( m_line, m_column ); 9.96 + } 9.97 + 9.98 + if ( m_line[ m_column ] != '\"' ) 9.99 + { 9.100 + throw AsmException_SyntaxError_EmptyExpression( m_line, m_column ); 9.101 + } 9.102 + 9.103 + // string 9.104 + size_t endQuotePos = m_line.find_first_of( '\"', m_column + 1 ); 9.105 + 9.106 + if ( endQuotePos == string::npos ) 9.107 + { 9.108 + throw AsmException_SyntaxError_MissingQuote( m_line, m_line.length() ); 9.109 + } 9.110 + else 9.111 + { 9.112 + string filename( m_line.substr( m_column + 1, endQuotePos - m_column - 1 ) ); 9.113 + 9.114 + try 9.115 + { 9.116 + ObjectCode::Instance().IncBin( filename.c_str() ); 9.117 + } 9.118 + catch ( AsmException_AssembleError& e ) 9.119 + { 9.120 + e.SetString( m_line ); 9.121 + e.SetColumn( m_column ); 9.122 + throw; 9.123 + } 9.124 + } 9.125 + 9.126 + m_column = endQuotePos + 1; 9.127 + 9.128 + if ( AdvanceAndCheckEndOfStatement() ) 9.129 + { 9.130 + throw AsmException_SyntaxError_InvalidCharacter( m_line, m_column ); 9.131 + } 9.132 +} 9.133 + 9.134 + 9.135 + 9.136 +/*************************************************************************************************/ 9.137 +/** 9.138 LineParser::HandleEqub() 9.139 */ 9.140 /*************************************************************************************************/ 9.141 @@ -868,6 +965,18 @@ 9.142 9.143 /*************************************************************************************************/ 9.144 /** 9.145 + LineParser::HandleOpenBrace() 9.146 +*/ 9.147 +/*************************************************************************************************/ 9.148 +void LineParser::HandleOpenBrace() 9.149 +{ 9.150 + m_sourceFile->OpenBrace( m_line, m_column - 1 ); 9.151 +} 9.152 + 9.153 + 9.154 + 9.155 +/*************************************************************************************************/ 9.156 +/** 9.157 LineParser::HandleNext() 9.158 */ 9.159 /*************************************************************************************************/ 9.160 @@ -888,6 +997,20 @@ 9.161 9.162 /*************************************************************************************************/ 9.163 /** 9.164 + LineParser::HandleCloseBrace() 9.165 + 9.166 + Braces for scoping variables are just FORs in disguise... 9.167 +*/ 9.168 +/*************************************************************************************************/ 9.169 +void LineParser::HandleCloseBrace() 9.170 +{ 9.171 + m_sourceFile->CloseBrace( m_line, m_column - 1 ); 9.172 +} 9.173 + 9.174 + 9.175 + 9.176 +/*************************************************************************************************/ 9.177 +/** 9.178 LineParser::HandleIf() 9.179 */ 9.180 /*************************************************************************************************/
10.1 --- a/src/expression.cpp Sun May 02 11:57:59 2010 +0100 10.2 +++ b/src/expression.cpp Sun May 02 12:04:21 2010 +0100 10.3 @@ -75,7 +75,11 @@ 10.4 { "INT", 10, &LineParser::EvalInt }, 10.5 { "ABS", 10, &LineParser::EvalAbs }, 10.6 { "SGN", 10, &LineParser::EvalSgn }, 10.7 - { "RND", 10, &LineParser::EvalRnd } 10.8 + { "RND", 10, &LineParser::EvalRnd }, 10.9 + { "NOT", 10, &LineParser::EvalNot }, 10.10 + { "LOG", 10, &LineParser::EvalLog }, 10.11 + { "LN", 10, &LineParser::EvalLn }, 10.12 + { "EXP", 10, &LineParser::EvalExp } 10.13 }; 10.14 10.15 10.16 @@ -841,6 +845,23 @@ 10.17 10.18 /*************************************************************************************************/ 10.19 /** 10.20 + LineParser::EvalNot() 10.21 +*/ 10.22 +/*************************************************************************************************/ 10.23 +void LineParser::EvalNot() 10.24 +{ 10.25 + if ( m_valueStackPtr < 1 ) 10.26 + { 10.27 + throw AsmException_SyntaxError_MissingValue( m_line, m_column ); 10.28 + } 10.29 + m_valueStack[ m_valueStackPtr - 1 ] = static_cast< double >( 10.30 + ~static_cast< int >( m_valueStack[ m_valueStackPtr - 1 ] ) ); 10.31 +} 10.32 + 10.33 + 10.34 + 10.35 +/*************************************************************************************************/ 10.36 +/** 10.37 LineParser::EvalPosate() 10.38 */ 10.39 /*************************************************************************************************/ 10.40 @@ -1002,6 +1023,69 @@ 10.41 10.42 /*************************************************************************************************/ 10.43 /** 10.44 + LineParser::EvalLog() 10.45 +*/ 10.46 +/*************************************************************************************************/ 10.47 +void LineParser::EvalLog() 10.48 +{ 10.49 + if ( m_valueStackPtr < 1 ) 10.50 + { 10.51 + throw AsmException_SyntaxError_MissingValue( m_line, m_column ); 10.52 + } 10.53 + m_valueStack[ m_valueStackPtr - 1 ] = log10( m_valueStack[ m_valueStackPtr - 1 ] ); 10.54 + 10.55 + if ( errno == EDOM || errno == ERANGE ) 10.56 + { 10.57 + throw AsmException_SyntaxError_IllegalOperation( m_line, m_column - 1 ); 10.58 + } 10.59 +} 10.60 + 10.61 + 10.62 + 10.63 +/*************************************************************************************************/ 10.64 +/** 10.65 + LineParser::EvalLn() 10.66 +*/ 10.67 +/*************************************************************************************************/ 10.68 +void LineParser::EvalLn() 10.69 +{ 10.70 + if ( m_valueStackPtr < 1 ) 10.71 + { 10.72 + throw AsmException_SyntaxError_MissingValue( m_line, m_column ); 10.73 + } 10.74 + m_valueStack[ m_valueStackPtr - 1 ] = log( m_valueStack[ m_valueStackPtr - 1 ] ); 10.75 + 10.76 + if ( errno == EDOM || errno == ERANGE ) 10.77 + { 10.78 + throw AsmException_SyntaxError_IllegalOperation( m_line, m_column - 1 ); 10.79 + } 10.80 +} 10.81 + 10.82 + 10.83 + 10.84 +/*************************************************************************************************/ 10.85 +/** 10.86 + LineParser::EvalExp() 10.87 +*/ 10.88 +/*************************************************************************************************/ 10.89 +void LineParser::EvalExp() 10.90 +{ 10.91 + if ( m_valueStackPtr < 1 ) 10.92 + { 10.93 + throw AsmException_SyntaxError_MissingValue( m_line, m_column ); 10.94 + } 10.95 + m_valueStack[ m_valueStackPtr - 1 ] = exp( m_valueStack[ m_valueStackPtr - 1 ] ); 10.96 + 10.97 + if ( errno == ERANGE ) 10.98 + { 10.99 + throw AsmException_SyntaxError_IllegalOperation( m_line, m_column - 1 ); 10.100 + } 10.101 +} 10.102 + 10.103 + 10.104 + 10.105 +/*************************************************************************************************/ 10.106 +/** 10.107 LineParser::EvalSqrt() 10.108 */ 10.109 /*************************************************************************************************/
11.1 --- a/src/lineparser.h Sun May 02 11:57:59 2010 +0100 11.2 +++ b/src/lineparser.h Sun May 02 12:04:21 2010 +0100 11.3 @@ -108,16 +108,20 @@ 11.4 void HandlePrint(); 11.5 void HandleOrg(); 11.6 void HandleInclude(); 11.7 + void HandleIncBin(); 11.8 void HandleEqub(); 11.9 void HandleEquw(); 11.10 void HandleSave(); 11.11 void HandleFor(); 11.12 void HandleNext(); 11.13 + void HandleOpenBrace(); 11.14 + void HandleCloseBrace(); 11.15 void HandleIf(); 11.16 void HandleElse(); 11.17 void HandleEndif(); 11.18 void HandleAlign(); 11.19 void HandleSkip(); 11.20 + void HandleSkipTo(); 11.21 void HandleGuard(); 11.22 void HandleClear(); 11.23 11.24 @@ -163,6 +167,10 @@ 11.25 void EvalAbs(); 11.26 void EvalSgn(); 11.27 void EvalRnd(); 11.28 + void EvalNot(); 11.29 + void EvalLog(); 11.30 + void EvalLn(); 11.31 + void EvalExp(); 11.32 11.33 11.34 SourceFile* m_sourceFile;
12.1 --- a/src/main.cpp Sun May 02 11:57:59 2010 +0100 12.2 +++ b/src/main.cpp Sun May 02 12:04:21 2010 +0100 12.3 @@ -23,7 +23,7 @@ 12.4 using namespace std; 12.5 12.6 12.7 -#define VERSION "0.02" 12.8 +#define VERSION "0.03" 12.9 12.10 12.11 /*************************************************************************************************/ 12.12 @@ -53,6 +53,7 @@ 12.13 12.14 } state = READY; 12.15 12.16 + bool bDumpSymbols = false; 12.17 12.18 GlobalData::Create(); 12.19 12.20 @@ -84,6 +85,10 @@ 12.21 { 12.22 GlobalData::Instance().SetVerbose( true ); 12.23 } 12.24 + else if ( strcmp( argv[i], "-d" ) == 0 ) 12.25 + { 12.26 + bDumpSymbols = true; 12.27 + } 12.28 else if ( strcmp( argv[i], "--help" ) == 0 ) 12.29 { 12.30 cout << "beebasm " VERSION << endl << endl; 12.31 @@ -93,6 +98,7 @@ 12.32 cout << " -do <file> Specify a disc image file to output" << endl; 12.33 cout << " -boot <file> Specify a filename to be run by !BOOT on a new disc image" << endl; 12.34 cout << " -v Verbose output" << endl; 12.35 + cout << " -d Dump all global symbols after assembly" << endl; 12.36 cout << " --help See this help again" << endl; 12.37 return EXIT_SUCCESS; 12.38 } 12.39 @@ -196,6 +202,11 @@ 12.40 12.41 delete pDiscIm; 12.42 12.43 + if ( bDumpSymbols && exitCode == EXIT_SUCCESS ) 12.44 + { 12.45 + SymbolTable::Instance().Dump(); 12.46 + } 12.47 + 12.48 ObjectCode::Destroy(); 12.49 SymbolTable::Destroy(); 12.50 GlobalData::Destroy();
13.1 --- a/src/objectcode.cpp Sun May 02 11:57:59 2010 +0100 13.2 +++ b/src/objectcode.cpp Sun May 02 12:04:21 2010 +0100 13.3 @@ -6,6 +6,7 @@ 13.4 13.5 #include <cstring> 13.6 #include <iostream> 13.7 +#include <fstream> 13.8 13.9 #include "objectcode.h" 13.10 #include "symboltable.h" 13.11 @@ -283,3 +284,37 @@ 13.12 } 13.13 memset( m_aFlags + start, 0, end - start ); 13.14 } 13.15 + 13.16 + 13.17 + 13.18 +/*************************************************************************************************/ 13.19 +/** 13.20 + ObjectCode::IncBin() 13.21 +*/ 13.22 +/*************************************************************************************************/ 13.23 +void ObjectCode::IncBin( const char* filename ) 13.24 +{ 13.25 + ifstream binfile; 13.26 + 13.27 + binfile.open( filename, ios_base::in | ios_base::binary ); 13.28 + 13.29 + if ( !binfile ) 13.30 + { 13.31 + throw AsmException_AssembleError_FileOpen(); 13.32 + } 13.33 + 13.34 + char c; 13.35 + 13.36 + while ( binfile.get( c ) ) 13.37 + { 13.38 + assert( binfile.gcount() == 1 ); 13.39 + Assemble1( static_cast< unsigned char >( c ) ); 13.40 + } 13.41 + 13.42 + if ( !binfile.eof() ) 13.43 + { 13.44 + throw AsmException_AssembleError_FileRead(); 13.45 + } 13.46 + 13.47 + binfile.close(); 13.48 +}
14.1 --- a/src/objectcode.h Sun May 02 11:57:59 2010 +0100 14.2 +++ b/src/objectcode.h Sun May 02 12:04:21 2010 +0100 14.3 @@ -28,6 +28,7 @@ 14.4 void Assemble1( unsigned int opcode ); 14.5 void Assemble2( unsigned int opcode, unsigned int val ); 14.6 void Assemble3( unsigned int opcode, unsigned int addr ); 14.7 + void IncBin( const char* filename ); 14.8 14.9 void SetGuard( int i ); 14.10 void Clear( int start, int end, bool bAll = true );
15.1 --- a/src/sourcefile.cpp Sun May 02 11:57:59 2010 +0100 15.2 +++ b/src/sourcefile.cpp Sun May 02 12:04:21 2010 +0100 15.3 @@ -125,16 +125,26 @@ 15.4 throw AsmException_FileError_ReadSourceFile( m_pFilename ); 15.5 } 15.6 15.7 - // Check that we have no FOR mismatch 15.8 + // Check that we have no FOR / braces mismatch 15.9 15.10 if ( m_forStackPtr > 0 ) 15.11 { 15.12 For& mismatchedFor = m_forStack[ m_forStackPtr - 1 ]; 15.13 15.14 - AsmException_SyntaxError_ForWithoutNext e( mismatchedFor.m_line, mismatchedFor.m_column ); 15.15 - e.SetFilename( m_pFilename ); 15.16 - e.SetLineNumber( mismatchedFor.m_lineNumber ); 15.17 - throw e; 15.18 + if ( mismatchedFor.m_step == 0.0 ) 15.19 + { 15.20 + AsmException_SyntaxError_MismatchedBraces e( mismatchedFor.m_line, mismatchedFor.m_column ); 15.21 + e.SetFilename( m_pFilename ); 15.22 + e.SetLineNumber( mismatchedFor.m_lineNumber ); 15.23 + throw e; 15.24 + } 15.25 + else 15.26 + { 15.27 + AsmException_SyntaxError_ForWithoutNext e( mismatchedFor.m_line, mismatchedFor.m_column ); 15.28 + e.SetFilename( m_pFilename ); 15.29 + e.SetLineNumber( mismatchedFor.m_lineNumber ); 15.30 + throw e; 15.31 + } 15.32 } 15.33 15.34 // Check that we have no IF mismatch 15.35 @@ -153,7 +163,7 @@ 15.36 15.37 if ( GlobalData::Instance().IsFirstPass() ) 15.38 { 15.39 - cout << "Processed file '" << m_pFilename << "' ok" << endl << endl; 15.40 + cerr << "Processed file '" << m_pFilename << "' ok" << endl << endl; 15.41 } 15.42 } 15.43 15.44 @@ -201,6 +211,38 @@ 15.45 15.46 /*************************************************************************************************/ 15.47 /** 15.48 + SourceFile::OpenBrace() 15.49 + 15.50 + Braces for scoping variables are just FORs in disguise... 15.51 +*/ 15.52 +/*************************************************************************************************/ 15.53 +void SourceFile::OpenBrace( string line, int column ) 15.54 +{ 15.55 + if ( m_forStackPtr == MAX_FOR_LEVELS ) 15.56 + { 15.57 + throw AsmException_SyntaxError_TooManyFORs( line, column ); 15.58 + } 15.59 + 15.60 + // Fill in FOR block 15.61 + 15.62 + m_forStack[ m_forStackPtr ].m_varName = ""; 15.63 + m_forStack[ m_forStackPtr ].m_current = 1.0; 15.64 + m_forStack[ m_forStackPtr ].m_end = 0.0; 15.65 + m_forStack[ m_forStackPtr ].m_step = 0.0; 15.66 + m_forStack[ m_forStackPtr ].m_filePtr = 0; 15.67 + m_forStack[ m_forStackPtr ].m_id = GlobalData::Instance().GetNextForId(); 15.68 + m_forStack[ m_forStackPtr ].m_count = 0; 15.69 + m_forStack[ m_forStackPtr ].m_line = line; 15.70 + m_forStack[ m_forStackPtr ].m_column = column; 15.71 + m_forStack[ m_forStackPtr ].m_lineNumber = m_lineNumber; 15.72 + 15.73 + m_forStackPtr++; 15.74 +} 15.75 + 15.76 + 15.77 + 15.78 +/*************************************************************************************************/ 15.79 +/** 15.80 SourceFile::UpdateFor() 15.81 */ 15.82 /*************************************************************************************************/ 15.83 @@ -213,6 +255,13 @@ 15.84 15.85 For& thisFor = m_forStack[ m_forStackPtr - 1 ]; 15.86 15.87 + // step of 0.0 here means that the 'for' is in fact an open brace, so throw an error 15.88 + 15.89 + if ( thisFor.m_step == 0.0 ) 15.90 + { 15.91 + throw AsmException_SyntaxError_NextWithoutFor( line, column ); 15.92 + } 15.93 + 15.94 thisFor.m_current += thisFor.m_step; 15.95 15.96 if ( ( thisFor.m_step > 0.0 && thisFor.m_current > thisFor.m_end ) || 15.97 @@ -236,6 +285,34 @@ 15.98 15.99 /*************************************************************************************************/ 15.100 /** 15.101 + SourceFile::CloseBrace() 15.102 + 15.103 + Braces for scoping variables are just FORs in disguise... 15.104 +*/ 15.105 +/*************************************************************************************************/ 15.106 +void SourceFile::CloseBrace( string line, int column ) 15.107 +{ 15.108 + if ( m_forStackPtr == 0 ) 15.109 + { 15.110 + throw AsmException_SyntaxError_MismatchedBraces( line, column ); 15.111 + } 15.112 + 15.113 + For& thisFor = m_forStack[ m_forStackPtr - 1 ]; 15.114 + 15.115 + // step of non-0.0 here means that this a real 'for', so throw an error 15.116 + 15.117 + if ( thisFor.m_step != 0.0 ) 15.118 + { 15.119 + throw AsmException_SyntaxError_MismatchedBraces( line, column ); 15.120 + } 15.121 + 15.122 + m_forStackPtr--; 15.123 +} 15.124 + 15.125 + 15.126 + 15.127 +/*************************************************************************************************/ 15.128 +/** 15.129 SourceFile::GetSymbolNameSuffix() 15.130 */ 15.131 /*************************************************************************************************/
16.1 --- a/src/sourcefile.h Sun May 02 11:57:59 2010 +0100 16.2 +++ b/src/sourcefile.h Sun May 02 12:04:21 2010 +0100 16.3 @@ -34,8 +34,8 @@ 16.4 16.5 // For loop / if related stuff 16.6 16.7 - #define MAX_FOR_LEVELS 16 16.8 - #define MAX_IF_LEVELS 16 16.9 + #define MAX_FOR_LEVELS 32 16.10 + #define MAX_IF_LEVELS 32 16.11 16.12 private: 16.13 16.14 @@ -69,6 +69,9 @@ 16.15 16.16 public: 16.17 16.18 + void OpenBrace( std::string line, int column ); 16.19 + void CloseBrace( std::string line, int column ); 16.20 + 16.21 void AddFor( std::string varName, 16.22 double start, 16.23 double end,
17.1 --- a/src/symboltable.cpp Sun May 02 11:57:59 2010 +0100 17.2 +++ b/src/symboltable.cpp Sun May 02 12:04:21 2010 +0100 17.3 @@ -5,12 +5,17 @@ 17.4 /*************************************************************************************************/ 17.5 17.6 #include <cmath> 17.7 +#include <iostream> 17.8 + 17.9 #include "symboltable.h" 17.10 17.11 + 17.12 +using namespace std; 17.13 + 17.14 + 17.15 SymbolTable* SymbolTable::m_gInstance = NULL; 17.16 17.17 17.18 - 17.19 /*************************************************************************************************/ 17.20 /** 17.21 SymbolTable::Create() 17.22 @@ -103,10 +108,10 @@ 17.23 @param int Its value 17.24 */ 17.25 /*************************************************************************************************/ 17.26 -void SymbolTable::AddSymbol( const std::string& symbol, double value ) 17.27 +void SymbolTable::AddSymbol( const std::string& symbol, double value, bool isLabel ) 17.28 { 17.29 assert( !IsSymbolDefined( symbol ) ); 17.30 - m_map.insert( make_pair( symbol, value ) ); 17.31 + m_map.insert( make_pair( symbol, Symbol( value, isLabel ) ) ); 17.32 } 17.33 17.34 17.35 @@ -123,7 +128,7 @@ 17.36 double SymbolTable::GetSymbol( const std::string& symbol ) const 17.37 { 17.38 assert( IsSymbolDefined( symbol ) ); 17.39 - return m_map.find( symbol )->second; 17.40 + return m_map.find( symbol )->second.GetValue(); 17.41 } 17.42 17.43 17.44 @@ -141,7 +146,7 @@ 17.45 void SymbolTable::ChangeSymbol( const std::string& symbol, double value ) 17.46 { 17.47 assert( IsSymbolDefined( symbol ) ); 17.48 - m_map.find( symbol )->second = value; 17.49 + m_map.find( symbol )->second.SetValue( value ); 17.50 } 17.51 17.52 17.53 @@ -160,3 +165,40 @@ 17.54 assert( IsSymbolDefined( symbol ) ); 17.55 m_map.erase( symbol ); 17.56 } 17.57 + 17.58 + 17.59 + 17.60 +/*************************************************************************************************/ 17.61 +/** 17.62 + SymbolTable::Dump() 17.63 + 17.64 + Dumps all global symbols in the symbol table 17.65 +*/ 17.66 +/*************************************************************************************************/ 17.67 +void SymbolTable::Dump() const 17.68 +{ 17.69 + cout << "[{"; 17.70 + 17.71 + bool bFirst = true; 17.72 + 17.73 + for ( map<string, Symbol>::const_iterator it = m_map.begin(); it != m_map.end(); ++it ) 17.74 + { 17.75 + const string& symbolName = it->first; 17.76 + const Symbol& symbol = it->second; 17.77 + 17.78 + if ( symbol.IsLabel() && 17.79 + symbolName.find_first_of( '@' ) == string::npos ) 17.80 + { 17.81 + if ( !bFirst ) 17.82 + { 17.83 + cout << ","; 17.84 + } 17.85 + 17.86 + cout << "'" << symbolName << "':" << symbol.GetValue() << "L"; 17.87 + 17.88 + bFirst = false; 17.89 + } 17.90 + } 17.91 + 17.92 + cout << "}]" << endl; 17.93 +}
18.1 --- a/src/symboltable.h Sun May 02 11:57:59 2010 +0100 18.2 +++ b/src/symboltable.h Sun May 02 12:04:21 2010 +0100 18.3 @@ -21,19 +21,37 @@ 18.4 static void Destroy(); 18.5 static inline SymbolTable& Instance() { assert( m_gInstance != NULL ); return *m_gInstance; } 18.6 18.7 - void AddSymbol( const std::string& symbol, double value ); 18.8 + void AddSymbol( const std::string& symbol, double value, bool isLabel = false ); 18.9 void ChangeSymbol( const std::string& symbol, double value ); 18.10 double GetSymbol( const std::string& symbol ) const; 18.11 bool IsSymbolDefined( const std::string& symbol ) const; 18.12 void RemoveSymbol( const std::string& symbol ); 18.13 18.14 + void Dump() const; 18.15 + 18.16 18.17 private: 18.18 18.19 + class Symbol 18.20 + { 18.21 + public: 18.22 + 18.23 + Symbol( double value, bool isLabel ) : m_value( value ), m_isLabel( isLabel ) {} 18.24 + 18.25 + void SetValue( double d ) { m_value = d; } 18.26 + double GetValue() const { return m_value; } 18.27 + bool IsLabel() const { return m_isLabel; } 18.28 + 18.29 + private: 18.30 + 18.31 + double m_value; 18.32 + bool m_isLabel; 18.33 + }; 18.34 + 18.35 SymbolTable(); 18.36 ~SymbolTable(); 18.37 18.38 - std::map<std::string, double> m_map; 18.39 + std::map<std::string, Symbol> m_map; 18.40 18.41 static SymbolTable* m_gInstance; 18.42 };
