I remember when I got my old 1982 IBM PC (I checked the ROM date), and I discovered that DOS debug had a command to assemble assembly language code typed in. Of course, it didn't support any of those fancy features like macros or labels.

I went to the library and got a book on 80x86 real mode assembly language programming, and started hacking away. My best program was probably the maze generator that created a 159x99 logical maze using a simple backtracking algorithm. It was extremely fast! By the time the video card changed from text mode to graphics mode, the thing was already done. And, it only took 458 bytes.

I'll do you one better.

Back, just after I got my first real computer (a 286), I made the great climb from Basic (or, rather, the incarnation known as BasicA) to Microsoft QBasic (no line numbers needed, text labels, actual real functions), and then up to Pascal. My compiler was Borland's Turbo Pascal 3.0 (and I still have the shortcut keys hardwired into my brain), which could make for real executable files out of my miles of underwhelming code.

My one interest at this time, and a main one ever since, was graphics programming. I'm talking the big mode 13h. 256 colors (indexed, of course), with a resolution 320x200. After tinkering around with text-mode, there's nothing like a little lava demo magic; you'll never go back. Unfortunately, Turbo Pascal 3.0 had two sets of graphical functions: turtle graphics (ugh!), and some dreadfully slow drawpixel/drawline routines.

So, being the evil little reverse-engineer that I was at the time (and, as I had neither an internet connection or any reference books of any sort on the subject), I decided I would take apart the compiled code from a simple program I wrote and see if I couldn't speed it up a bit. And there began my long, rather racy affair with x86 assembly language.

See, the only assembly I could insert into my pascal programs was actually direct machine code (in the form of an inline(FF/FF/FF/FF) directive, where the FFs are the bytes machine code. So, I wrote a small program that inserted a string, inline, just before a call to the putpixel routine. Then the program exited. I compiled this program, and opened it in good old DOS debug, and did a string search (the actual string was "012345," which I was fairly certain was not going to occur, um, naturally, in a string of machine code) and traced the code until I found the putpixel routine, which I then fiddled around with in debug until I came across a faster way to place a pixel on the screen in mode 13h (basically, the problem was the putpixel routine assumed that the pixel color changed every time, which means a lot of OUTs were wasted, which are expensive). Then, I wrote down the machine code into my notebook, byte by byte, fired up Turbo Pascal, and wrote myself a couple functions (basically consisting of inline(...) directives) that did something on the order of quadrupling the speed of my graphics code. It was still rather slow, but I got to feel like a hacker.
Here's a very short MS-DOS debug "script" that will make the screen flash madly until you hit escape. Very fun when at parties where someone use their win9x computer for playing mp3s.

    mov ax, 13
    int 10
    mov ax, a000
    mov es, ax
    mov cx, ffff
    in al, 40
    rep stosb
    in al, 60
    dec al
    jnz 010a
  hit enter on a blank line

Here's a short explanation of what's going on:

  • The two first lines sets 320x200x256 std vga gfx mode
  • The next two lines sets up es target segment to point to video ram at a000:0000
  • The next line sets the cx register to 65535, which will be the number of pixels we try to fill.
  • in al, 40 reads some motherboard timer which will produce a pseudo-random value
  • rep stosb fills video ram with this value. Since we're coding in 16bit realmode, we will wrap around, so it doesn't matter where in the a000 video ram segment we start and stop filling bytes
  • in al,60/dec al reads the keyboard controller and subtracts one
  • if the result is not zero, keep on looping. The result is zero when the keyboard controller returns 1 (for escape).
  • in which case we terminate our program.

Perhaps if you came to this node you were wondering how to write a .com file with DOS debug.

First you must either have a knowledge of assembly language (of which I have none), or a convenient program to type in (look up!).

When you are typing in the program in it will display memory locations on the left of every line. The first should be xxxx:0100. After you have finished writing the program, it will be xxxx:yyyy. Subtract the 0100 from the yyyy value on the last line (the line where you hit enter without typing anything.) For example, when I typed in the above assembly, it went from 106C:0100 to 106C:0118. 0118 - 0100 is 18. You will need this number in a second.

Now pick a name and location for your fancy new program. For the program above I decided it should be "flasher" and I would place it on the root of my C drive. Use the N command to tell the debug program this. Type "N C:\path\name.com". In my example I typed "N C:\flasher.com".

Do you still remember the number you got 2 paragraphs back? Now you need it. Type "R CX". Then type in that number.

For the final step, type "W" It should respond with "Writing <number> bytes". Check and see if it saved your fancy new program.

Side note: If you are using the program above, try changing the ffff in the 5th line to various other values for different effects.

Log in or register to write something here or to contact authors.