A collection of x86 MASM Assembly projects demonstrating progressive mastery of low-level programming — from sorting algorithms and array manipulation to string primitive I/O and macro design.
| Project | Title | Key Concepts |
|---|---|---|
| Project 5 | Random Number Generator, Sorter & Analyzer | Bubble sort, median, frequency analysis, Register Indirect addressing |
| Project 6 | String Primitives & Macro I/O | LODSB/STOSB, string conversion, overflow detection, custom macros |
Score: Full marks + Extra Credit
A 377-line x86 MASM program that generates 200 random integers, sorts them, finds the median, and produces a frequency count — all implemented with proper stack-based parameter passing and reusable procedure design.
- Generates 200 random integers between 15 and 50
- Displays the unsorted list (20 numbers per line)
- Sorts the array in ascending order using bubble sort
- Calculates and displays the median value
- Displays the sorted list
- Counts and displays the frequency of each possible number in the range
Bubble Sort in Assembly
sortListprocedure implements a bubble sort usingESI/EDIfor array traversalexchangeElementssub-procedure swaps adjacent elements using Register Indirect addressing ([EDI+EDX*4])
Median Calculation
- Handles both odd and even array sizes correctly
- For even arrays: averages the two middle values with proper rounding logic using
IDIVand remainder checking
Frequency Analysis
countListprocedure uses nested loops to count instances of each number in the range[LO..HI]- Builds a separate counts array using Base+Offset addressing
Reusable Procedure Design
displayListis called three times with different arrays and sizes — demonstrating clean parameter-driven procedure design- Clean procedure hierarchy:
main→introduction,fillArray,displayList,sortList,displayMedian,countList,goodbye
Low-Level Requirements Met
- ✅ All parameters passed on the runtime stack (STDCALL)
- ✅ Register Indirect addressing for array elements (
[ESI+EDX*4]) - ✅ Base+Offset addressing for stack parameters
- ✅ All registers saved and restored by called procedures
- ✅ Stack cleaned up by called procedures (
RET n)
Score: 51/50 — Full marks plus extra credit 🎉
A 533-line x86 MASM Assembly program demonstrating mastery of low-level I/O procedures, string primitive instructions, macro design, and stack-based parameter passing — the portfolio capstone project for CS271.
Yes, that ASCII art "HAPPY HOLIDAYS" is rendered entirely in raw byte values — because why not? 😄
Collects 10 signed 32-bit integers from the user, validates each one, stores them in an array, and displays:
- The list of entered numbers
- Their sum
- Their truncated average
- A running subtotal after each entry (extra credit)
- Line numbers for each prompt (extra credit)
Custom Macros
mGetString— displays a prompt and reads user keyboard input into memory usingReadString, withPUSHAD/POPADregister preservationmDisplayString— prints a string at a given memory address usingWriteString
Custom Procedures
ReadVal— converts user string input to a signed 32-bit integer (SDWORD) usingLODSBstring primitives, with full input validationWriteVal— converts a signed 32-bit integer back to an ASCII string usingSTOSBstring primitives, then displays itConvert— sub-procedure ofReadValhandling place-value arithmetic of ASCII-to-integer conversion
Input Validation
- Rejects non-numeric characters
- Handles
+and-sign prefixes - Detects and rejects numbers too large for a 32-bit register using overflow detection (
JO) - Re-prompts user on any invalid input including empty input
Low-Level Requirements Met
- ✅
LODSBandSTOSBused for all string primitive operations - ✅ All parameters passed on the runtime stack using STDCALL calling convention
- ✅ All registers saved and restored by called procedures and macros
- ✅ Stack cleaned up by called procedures (
RET n) - ✅ No global variable references outside of
main - ✅ Register Indirect addressing for array elements
- ✅ Base+Offset addressing for stack parameters
- ✅ Local variables used appropriately via
LOCALdirective
Extra Credit Implemented
- Line numbering — each user prompt is numbered sequentially using
WriteVal - Running subtotal — displays a running total after each valid entry using
WriteVal
main
├── introduction
├── Randomize
├── fillArray (200 random integers)
├── displayList (unsorted)
├── sortList
│ └── exchangeElements (bubble sort swap)
├── displayMedian
├── displayList (sorted)
├── countList (frequency analysis)
├── displayList (counts)
└── goodbye
main
├── mDisplayString (intro, directions)
├── Loop 10x:
│ ├── WriteVal (line number)
│ ├── ReadVal
│ │ ├── mGetString (get user input)
│ │ ├── Validate input character by character (LODSB)
│ │ └── Convert (ASCII → SDWORD)
│ └── WriteVal (running total)
├── Display array (WriteVal per element)
├── Display sum (WriteVal)
├── Display average (WriteVal)
└── ASCII art farewell 🎄
These projects pushed me to think at the hardware level — every byte matters, every register has a purpose, and there is no abstraction to hide behind. Key takeaways:
- Sorting at the register level — implementing bubble sort with direct memory manipulation gave me a deep appreciation for what
Array.sort()does under the hood - String primitives —
LODSB/STOSBare elegant tools once you understand the direction flag and how ESI/EDI advance automatically - Stack discipline — managing the runtime stack manually, including cleaning up with
RET n, gave me a deep appreciation for what high-level languages handle automatically - Overflow detection — using
JOto catch 32-bit register overflow during conversion was one of the most satisfying debugging moments of the project - Reusable procedures — designing
displayListto work with multiple arrays taught me how parameter-driven design works at the lowest level
- Windows
- Visual Studio with MASM support
- Irvine32 library
- Clone the repo
- Open the desired
.asmfile in Visual Studio - Ensure Irvine32.inc is configured in your include path
- Build and run
Aimee Wirick Oregon State University — B.S. Computer Science, Expected June 2026 LinkedIn • AimeeWirick.com • GitHub
