PyASM-Sim is a simulator for a custom, simple assembly-like language, built entirely in Python using the PLY (Python Lex-Yacc) library. It parses and executes assembly code, managing a simulated memory architecture with registers, memory, and program control flow. The project demonstrates the power of PLY for creating parsers and interpreters for custom languages.
- Custom Assembly Language: A well-defined instruction set for memory, arithmetic, logical, and control flow operations.
- Labeled Instructions: Supports labels for branching and looping, enabling complex control flow.
- Simulated Memory: Implements a register-based architecture with a separate main memory space.
- Multiple Addressing Modes:
- Immediate:
STOR A, 10 - Register:
SUM A, B - Direct (Register Indirect):
STOR @A, 100(uses the value in registerAas a memory address)
- Immediate:
- Rich Data Type Support: Natively handles Integers, Floats, and Strings.
- Comprehensive Instruction Set: Includes arithmetic (
SUM,DIV), logical (AND,NOT), string manipulation (CONCAT,SUBSTR), and control flow (IF,GOTO) instructions. - Robust Parsing: Built with the PLY library, ensuring reliable and efficient parsing of the source code.
- Detailed Error Handling: Catches both syntax errors during parsing and runtime errors (e.g., division by zero, invalid types, undefined labels) during execution.
The language uses a simple format where each line can have an optional label followed by an instruction, separated by $$$.
LABEL $$$ INSTRUCTION operand1, operand2, ...If a line has no label, it starts directly with the instruction.
-
STOR dest, value: Stores avalueinto a destination register or memory address.L1 $$$ STOR A, 10 ; A = 10 L2 $$$ STOR B, "Hello" ; B = "Hello" L3 $$$ STOR @A, 50 ; Memory[A] (i.e., Memory[10]) = 50
-
SUM reg1, reg2/value:reg1 = reg1 + reg2/value -
SUB reg1, reg2/value:reg1 = reg1 - reg2/value -
MUL reg1, reg2/value:reg1 = reg1 * reg2/value -
DIV reg1, reg2/value:reg1 = reg1 / reg2/value(Floating-point division) -
MOD reg1, reg2/value:reg1 = reg1 % reg2/valueSUM A, 5 ; A = A + 5 SUB B, C ; B = B - C DIV D, @A ; D = D / Memory[A]
-
AND reg1, reg2/value:reg1 = reg1 & reg2/value -
OR reg1, reg2/value:reg1 = reg1 | reg2/value -
XOR reg1, reg2/value:reg1 = reg1 ^ reg2/value -
NOT reg:reg = ~reg -
SHL reg, shift_value:reg = reg << shift_value -
SHR reg, shift_value:reg = reg >> shift_valueSHL A, 2 ; A = A << 2 NOT B ; B = ~B
-
CONCAT reg1, reg2/value: Concatenates the string inreg2/valuetoreg1.reg1 = reg1 + reg2/value. -
LENGTH dest_reg, src_reg/value: Stores the length of the string insrc_reg/valueintodest_reg. -
SUBSTR reg, pos1, pos2: Extracts a substring fromregfrompos1(inclusive) topos2(exclusive).STOR A, "Hello" STOR B, " World" CONCAT A, B ; A is now "Hello World" LENGTH C, A ; C is now 11 SUBSTR A, 0, 5 ; A is now "Hello"
-
GOTO label: Unconditionally jumps to the specifiedlabel. -
IF condition INSTRUCTION: Executes theINSTRUCTIONonly if theconditionis true.- Conditions:
reg == value,reg != value,reg > value,reg < value
- Conditions:
-
HLT: Stops program execution and prints the final state of all registers and memory.STOR COUNT, 5 LOOP $$$ SUB COUNT, 1 PRINT COUNT IF COUNT > 0 GOTO LOOP HLT
-
PRINT reg/mem_addr: Prints the value of a register or memory location to the console.PRINT A ; Prints value of register A PRINT @B ; Prints value from Memory[B]
- Python 3.8+
- PLY library
-
Clone the repository:
git clone https://github.com/Bivas-Biswas/PyASM-Sim.git cd PyASM-Sim -
Install dependencies:
pip install ply
-
Create your assembly file (e.g.,
program.asm) or use one of the examples provided. -
Execute the simulator:
python main.py program.asm
The output of the
PRINTstatements and the final memory dump fromHLTwill be displayed in the terminal.
This program calculates the factorial of a number (e.g., 5) and prints the result.
factorial.asm
; PyASM-Sim Program to Calculate Factorial of 5
STOR N, 5 ; The number to find the factorial of
STOR RES, 1 ; Initialize result to 1
STOR I, 1 ; Initialize loop counter i to 1
LOOP $$$ SUM I, 1 ; i = i + 1
MUL RES, I ; result = result * i
IF I < N GOTO LOOP ; If i is still less than N, continue loop
PRINT RES ; Print the final result
HLT ; Halt executionRunning the program:
python main.py factorial.asmExpected Output:
120
=======================================
HALTING
=======================================
FINAL REGISTER STATE:
N: 5
RES: 120
I: 5
FINAL MEMORY STATE:
{...}
=======================================
The simulator is designed to be robust and provides clear error messages for various issues:
- Syntax Errors: The parser will report invalid syntax, the unexpected token, and the line number.
SyntaxError: Unexpected token 'INVALID_OP' at line 5
- Runtime Errors: The executor handles errors that occur during the program's run.
- NameError:
Undefined label 'UNDEFINED_LABEL' referenced at line 10. - TypeError:
Unsupported operand type for SUM: 'int' and 'str' at line 8. - ValueError:
Cannot perform logical NOT on non-integer value in register B at line 12. - ZeroDivisionError:
Division by zero at line 6.
- NameError: