📄 assembler.java
字号:
import java.util.*;
import java.io.*;
public
class Assembler
{
public static AssemblyResults assemble( String source, int location, Box box, CPU CPUBox, Memory memory )
{
AssemblySourceProgram code = new AssemblySourceProgram( source );
int memoryCounter = location;
Vector assemblyErrorVector = new Vector();
int errorCount = 0;
// Loop to check for valid code
for ( int lineIndex = 1; lineIndex <= code.sourceLineLength();
lineIndex++ )
{
box.showStatus( "Assembling . . . Checking line " + lineIndex );
AssemblySourceLine line = code.getSourceLineByLineNumber(
lineIndex );
if ( ( line != null ) && ( line.sourceTokenLength() > 0 ) )
{
String[] tokens = line.getSourceTokenStringArray();
int offset=0;
if(IsLabel(tokens[0])){
offset=1;
}
if ( ORG.equalsIgnoreCase( tokens[ 0 + offset ] ) )
{
if ( tokens.length - offset < 2 )
{
errorCount++;
assemblyErrorVector.addElement( new AssemblyError(
lineIndex, "ORG expects one operand" ) );
}
else if ( tokens.length - offset > 2 )
{
errorCount++;
assemblyErrorVector.addElement( new AssemblyError(
lineIndex, "ORG does not accept more than one " +
"operand" ) );
}
else if ( ! AssemblyInstruction.isAddress( tokens[ 1 + offset ] ))
{
errorCount++;
assemblyErrorVector.addElement( new AssemblyError(
lineIndex, "Specified address is invalid" ) );
}
}
else if ( DB.equalsIgnoreCase( tokens[ 0 + offset ] ) )
{
if ( tokens.length - offset < 2 )
{
errorCount++;
assemblyErrorVector.addElement( new AssemblyError(
lineIndex, "DB expects one operand" ) );
}
else if ( tokens.length - offset > 2 )
{
errorCount++;
assemblyErrorVector.addElement( new AssemblyError(
lineIndex, "DB does not accept more than one " +
"operand" ) );
}
else if ( AssemblyInstruction.toByteShort( tokens[ 1 + offset ] ) ==
-1 )
{
errorCount++;
assemblyErrorVector.addElement( new AssemblyError(
lineIndex, "Specified byte constant is invalid" ) );
}
}
else if ( DW.equalsIgnoreCase( tokens[ 0 + offset ] ) )
{
if ( tokens.length - offset < 2 )
{
errorCount++;
assemblyErrorVector.addElement( new AssemblyError(
lineIndex, "DW expects one operand" ) );
}
else if ( tokens.length - offset > 2 )
{
errorCount++;
assemblyErrorVector.addElement( new AssemblyError(
lineIndex, "DW does not accept more than one " +
"operand" ) );
}
else if ( AssemblyInstruction.toWordInteger( tokens[ 1 + offset ] )
== -1 )
{
errorCount++;
assemblyErrorVector.addElement( new AssemblyError(
lineIndex, "Specified word constant is invalid" ) );
}
}
else if ( AssemblyInstruction.isMnemonic( tokens[ 0 + offset ] ) )
{
if ( AssemblyInstruction.expectsOperands( tokens[ 0 + offset ] ) ==
1 )
{
if ( tokens.length - offset < 2 )
{
errorCount++;
assemblyErrorVector.addElement( new AssemblyError(
lineIndex, tokens[ 0 + offset ].toUpperCase() + " expects "
+ "one operand" ) );
}
else if ( tokens.length - offset > 2 )
{
errorCount++;
assemblyErrorVector.addElement( new AssemblyError(
lineIndex, tokens[ 0 + offset ].toUpperCase() + " does not "
+ "accept more than one operand" ) );
}
else if ( !AssemblyInstruction.isAddress( tokens[
1 + offset ]) && (!LabelExists(tokens[ 1 + offset ],code)) )
{
errorCount++;
assemblyErrorVector.addElement( new AssemblyError(
lineIndex, "Specified address is invalid" ) );
}
}
else
{
if ( tokens.length - offset > 1 )
{
errorCount++;
assemblyErrorVector.addElement( new AssemblyError(
lineIndex, tokens[ 0 + offset ].toUpperCase() + " does not "
+ "accept any operands" ) );
}
}
}
else
{
errorCount++;
assemblyErrorVector.addElement( new AssemblyError(
lineIndex, "Specified mnemonic is invalid" ) );
}
}
}
if ( errorCount != 0 )
{
box.showStatus( "Assembling . . . " + errorCount + " error(s) " +
"encountered" );
}
else
{
// If no errors exist, assemble program
// Places valid code in memory and temporary variables
for ( int lineIndex = 1; lineIndex <= code.sourceLineLength();
lineIndex++ )
{
box.showStatus( "Assembling . . . Assembling line " +
lineIndex );
// System.out.println( "DEBUG ==> Assembling line " + lineIndex );
AssemblySourceLine line = code.getSourceLineByLineNumber(
lineIndex );
if ( ( line != null ) && ( line.sourceTokenLength() > 0 ) )
{
String[] tokens = line.getSourceTokenStringArray();
int offset=0;
if(IsLabel(tokens[0])){
offset=1;
}
if ( ORG.equalsIgnoreCase( tokens[ 0 + offset ] ) )
{
memoryCounter = AssemblyInstruction.toAddressInteger(
tokens[ 1 ] );
}
else if ( DB.equalsIgnoreCase( tokens[ 0 + offset ] ) )
{
short byteShort = AssemblyInstruction.toByteShort(
tokens[ 1 ] );
memory.write( memoryCounter, byteShort );
// String[] binaryNybble = toBinaryNybble( byteShort );
// memory[ memoryCounter ] = binaryNybble;
memoryCounter++;
}
else if ( DW.equalsIgnoreCase( tokens[ 0 + offset ] ) )
{
short[] wordCode = AssemblyInstruction.toWordCode(
AssemblyInstruction.toWordInteger( tokens[ 1 + offset ] ) );
memory.write( memoryCounter, wordCode[ 0 ] );
memory.write( memoryCounter + 1, wordCode[ 1 ] );
// String[] binaryNybble = toBinaryNybble( wordCode[ 0 ] );
// memory[ memoryCounter ] = binaryNybble;
// binaryNybble = toBinaryNybble( wordCode[ 1 ] );
// memory[ memoryCounter + 1 ] = binaryNybble;
memoryCounter += 2;
}
else
{
code.setSourceLineAddressByLineNumber( memoryCounter,
lineIndex );
// opcode[ memoryCounter ] = tokens[ 0 ].toUpperCase();
// String[] binaryNybble = toBinaryNybble(
// AssemblyInstruction.toMnemonicCode( tokens[ 0 ] ) );
// memory[ memoryCounter ] = binaryNybble;
if ( AssemblyInstruction.expectsOperands( tokens[
0 + offset ] ) == 1 )
{
short[] addressCode;
if(LabelExists(tokens[ 1 + offset ],code)){
addressCode = AssemblyInstruction.
toAddressCode(GetLabelAddress(tokens[ 1 + offset ],code));
}else{
addressCode = AssemblyInstruction.
toAddressCode( AssemblyInstruction.
toAddressInteger( tokens[ 1 + offset ] ) );
}
// String[] binaryNybbleAddress = toBinaryNybble(
// addressCode[ 0 ] );
short instr=AssemblyInstruction.toMnemonicCode( tokens[ 0 + offset ] );
if (instr != 0xff){
instr = (short) (instr << 6);
}
memory.write( memoryCounter, (short) (instr | addressCode[ 0 ]) );
// memory[ memoryCounter + 1 ] = binaryNybbleAddress;
// binaryNybbleAddress = toBinaryNybble( addressCode[
// 1 ] );
//memory.write( memoryCounter + 2, addressCode[ 1 ] );
// memory[ memoryCounter + 2 ] = binaryNybbleAddress;
//memoryCounter += 2;
}
else{
short instr=AssemblyInstruction.toMnemonicCode( tokens[ 0 + offset ] );
if (instr != 0xff){
instr = (short) (instr << 6);
}
memory.write( memoryCounter, instr );
}
memoryCounter++;
}
}
}
}
box.showStatus( " ");
CPUBox.getMemory().repaint();
// System.out.println( "DEBUG ==> Copying errors into array..." );
AssemblyError[] assemblyErrors = new AssemblyError[
assemblyErrorVector.size() ];
assemblyErrorVector.copyInto( assemblyErrors );
box.showStatus( "Assembly Complete");
return ( new AssemblyResults( assemblyErrors, code ) );
}
//Needed in order to find a label
private static boolean IsLabel(String token){
if(token.indexOf(':')!=-1 && token.indexOf(':')==token.length()-1 && token.length()>1){
return true;
}else{
return false;
}
}
private static boolean LabelExists(String label,AssemblySourceProgram code){
for ( int lineIndex = 1; lineIndex <= code.sourceLineLength(); lineIndex++ )
{
AssemblySourceLine line = code.getSourceLineByLineNumber(lineIndex);
if(line != null && line.GetLabel().toLowerCase().equals(label.toLowerCase()+":")){
return true;
}
}
return false;
}
private static int GetLabelAddress(String label,AssemblySourceProgram code){
if(LabelExists(label,code)){
int memoryCounter=0;
for ( int lineIndex = 1; lineIndex <= code.sourceLineLength();
lineIndex++ )
{
AssemblySourceLine line = code.getSourceLineByLineNumber(
lineIndex );
if(line != null && line.GetLabel().toLowerCase().equals(label.toLowerCase()+":")){
return memoryCounter;//line.getAddress();
}
if ( ( line != null ) && ( line.sourceTokenLength() > 0 ) )
{
String[] tokens = line.getSourceTokenStringArray();
int offset=0;
if(IsLabel(tokens[0])){
offset=1;
}
if ( ORG.equalsIgnoreCase( tokens[ 0 + offset ] ) )
{
memoryCounter = AssemblyInstruction.toAddressInteger(
tokens[ 1 ] );
}
else if ( DB.equalsIgnoreCase( tokens[ 0 + offset ] ) )
{
memoryCounter++;
}
else if ( DW.equalsIgnoreCase( tokens[ 0 + offset ] ) )
{
memoryCounter += 2;
}
else
{
memoryCounter++;
}
}
}
}
return -1;
}
public static String[] toBinaryNybble( short byteShort )
{
String upperNybble = Integer.toString( byteShort / 0x10, 2 );
String lowerNybble = Integer.toString( byteShort % 0x10, 2 );
while ( upperNybble.length() < 4 )
{
upperNybble = "0" + upperNybble;
}
while ( lowerNybble.length() < 4 )
{
lowerNybble = "0" + lowerNybble;
}
String[] binaryNybble = { upperNybble, lowerNybble };
return ( binaryNybble );
}
// String constants for each assembly instruction
// public static final String NOP = new String( "NOP" );
// public static final String LDAC = new String( "LDAC" );
// public static final String STAC = new String( "STAC" );
// public static final String MVAC = new String( "MVAC" );
// public static final String MOVR = new String( "MOVR" );
public static final String JMP = new String( "JMP" );
// public static final String JMPZ = new String( "JMPZ" );
// public static final String JPNZ = new String( "JPNZ" );
public static final String ADD = new String( "ADD" );
// public static final String SUB = new String( "SUB" );
public static final String INC = new String( "INC" );
// public static final String CLAC = new String( "CLAC" );
public static final String AND = new String( "AND" );
// public static final String OR = new String( "OR" );
// public static final String XOR = new String( "XOR" );
// public static final String NOT = new String( "NOT" );
public static final String END = new String( "END" );
public static final String ORG = new String( "ORG" );
public static final String DB = new String( "DB" );
public static final String DW = new String( "DW" );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -