Image Map Image Map
No More Results
About neilobremski

Basic Information

About neilobremski
I started programming in GW-BASIC by copying and manipulating example listings given to me by a friend. I didn't have access to any books or other references so my initial education was trial and error alone. It was enough to hook me and now I find myself looking back fondly on those early days of struggle and excitement.
Seattle, USA
Hiking, Reading, Music
Computer Programmer



Total Posts
Total Posts
Posts Per Day
General Information
Last Activity
Today 09:00 AM
Join Date
October 9th, 2016
Home Page
View neilobremski's Blog

Recent Entries

Optimizing Double Buffer: C vs Asm

by neilobremski on February 16th, 2017 at 01:14 PM
There's no contest, right? C versus Assembler and you know the latter is going to crush the former. The question really becomes why and what you can do about it. But first I wanted to see just how fast I could make a double buffer for CGA.

As with previous entries, I'm using Microsoft C 5.10 as my baseline compiler. Your own compiler may get better or worse results but I've found this to be a good average as far as tools of the real mode era go (e.g. late 1980's). I created some helper

Read More

Updated February 16th, 2017 at 01:21 PM by neilobremski


Calling REP MOVSW in C

by neilobremski on February 16th, 2017 at 09:00 AM
What I'm about to show you will only work in 16-bit real-mode x86 compilers. The only built-in CRT functions you have for copying data from one place to another are things like memcpy(). And the problem with this function is it doesn't work on far pointers 1. Even if you have one that does, it works on bytes and not words, so it will be slower on 8086-based CPU's that have a 16-bit bus.

At any rate, the best way to copy data into a video buffer is through REP MOVSW but this requires

Read More

Updated February 16th, 2017 at 09:27 AM by neilobremski (Modified code to support Turbo C 2 and Power C)


x86 Assembly Local Variables

by neilobremski on February 15th, 2017 at 01:37 PM
The SS register stores the Stack Segment and the logical stack itself grows down. When you PUSH a register, its value is added at SS:SP and SP is decremented by 2. 1 A procedure's local variables, then, are allocated below SP by the amount of bytes required to store them.

Let's start by looking at a simple C function that merely declares some local variables, manipulates them, and then returns ...

void locals(void)
	char x, y, z;
	short a, b,

Read More



by neilobremski on February 14th, 2017 at 03:01 PM
The last few days I have been working my way through Jeff Duntemann's book, Assembly Language Step-By-Step (ISBN 978-0471578147), and my favorite part has been a gentle introduction into the DOS command DEBUG. My penchant for doing things the hard way has been particularly tickled by the ability to write assembler instructions in this old DOS utility.

Today I decided to see if I could combine what I have learned with what I already know about the CGA and BIOS routines by writing MAGENTA.COM

Read More

Updated February 14th, 2017 at 03:06 PM by neilobremski (Put under "Asm" category)


Caching in on the Z Divide

by neilobremski on February 9th, 2017 at 03:25 PM
Projecting a 3D point onto a 2D screen is probably the most basic thing one has to do and one of the most frequent. The calculation is to multiply a coordinate by the Viewing Distance (VD) and then divide by Depth (Z). This is done for both X (horizontal) and Y (vertical) axes and thus occurs twice per point. Magenta's Maze encapsulates this into the macros project_x() and project_y() which both contain this core equation:

((int)( ((long)(p) << VD) / (z)))
The primary

Read More

Updated February 10th, 2017 at 08:15 AM by neilobremski (Added 16-bit integer timing)