Skip to content
This repository was archived by the owner on Oct 27, 2026. It is now read-only.
Sentimenta1istPublic archive

About

Two-stage assembler for an x86 subset with listing and symbol tables (C++, 2020)

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Latest commit

 

History

61 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 

Repository files navigation

AsmCompiler

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)

What's inside

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

Interesting bits

  • The listing is produced line by line while a running location counter (DispMain) is advanced by the size of each encoded line (Displacement() in MachineCode.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 like Vd[esi*4]: it searches the register table for the index register followed by *, maps the scale character through ScaleTable, and falls back to base 101 when there is no explicit base. For example bts Vd[esi*4], eax is listed as 0F AB 84 B5 00000001.
  • Conditional assembly is done by IfDirectiveWorking(): if the IF operand is an EQU constant equal to 0, every line up to ENDIF gets a ; comment lexeme prepended, so it is skipped by the later stages.
  • Segment override prefixes (FS:Vd[esi*2]) are looked up in TableOfPrefixesSegment; segment sizes and the segment-register table are printed at the end (the sample gives DATA = 0x0E, CODE = 0x36).

Run

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.

Note

Written in 2020, before AI coding assistants. Kept as-is for history.

About

Two-stage assembler for an x86 subset with listing and symbol tables (C++, 2020)

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages