A small two-stage assembler for an Intel x86 (32-bit) subset, written in C++ with an earlier, unfinished Python prototype.
Year: 2020 · Language: C++14 (plus Python 3 prototype) · Context: university coursework (KPI)
| Path | What it does |
|---|---|
cpp/main.cpp |
Entry point: loads test.asm, prints lexical/syntax tables, then the listing |
cpp/Parsing.cpp |
Reads the source, splits each line into lexemes, classifies them (instruction, register, directive, label, constants, user id); handles IF/ENDIF |
cpp/FirstSecondStage.cpp |
Builds the per-line syntax structure (label / mnemonic / operand 1 / operand 2 positions) |
cpp/MachineCode.cpp |
Encodes instructions: prefix, opcode, ModR/M, SIB, displacement, immediate; builds the .lst-style listing |
cpp/Addition.cpp |
Hex helpers, operand type identification, segment and symbol tables output |
cpp/Base.cpp, Base.h |
Static tables: instruction encodings, registers, scale factors, segment prefixes |
cpp/ErrorCheck.cpp |
Checks for undefined identifiers and wrong operand combinations |
cpp/cmake-build-debug/test.asm |
Sample input program (the only file kept from that folder) |
python/ |
Earlier prototype (lexer, line typing, instruction table); machine_code.py and testing.py are empty |
- The listing is produced line by line while a running location counter (
DispMain) is advanced by the size of each encoded line (Displacement()inMachineCode.cpp); label addresses are written into the symbol table (MassOfUser) at the moment the label line is reached. SibOneLine()assembles the SIB byte for operands likeVd[esi*4]: it searches the register table for the index register followed by*, maps the scale character throughScaleTable, and falls back to base101when there is no explicit base. For examplebts Vd[esi*4], eaxis listed as0F AB 84 B5 00000001.- Conditional assembly is done by
IfDirectiveWorking(): if theIFoperand is anEQUconstant equal to 0, every line up toENDIFgets a;comment lexeme prepended, so it is skipped by the later stages. - Segment override prefixes (
FS:Vd[esi*2]) are looked up inTableOfPrefixesSegment; segment sizes and the segment-register table are printed at the end (the sample gives DATA = 0x0E, CODE = 0x36).
Verified with g++ (C++14) on Linux. The program opens test.asm from the current directory:
cd cpp
g++ -std=c++14 *.cpp -o asm
cd cmake-build-debug && ../asm
A cpp/CMakeLists.txt is also provided (not re-tested). The Python prototype was run with python3 main.py from a directory containing test.asm; it only prints lexemes and empty tables.
Written in 2020, before AI coding assistants. Kept as-is for history.