The World’s Smallest (Useful!) Program :)

Thought I’d share a funny little program with you from back in 1986. Here it is: to my knowledge the world’s smallest (useful) IBM PC computer program:

PUSH  AX
POP   DS
XOR   BYTE PTR [16], 7
RETF

That computer program in x86 assembler is exactly 9 bytes long and actually does do something useful— it toggles the print screen function (if it’s on, it turns it off and vice versa). It works based on some analysis of the IBM PC ROM BIOS listing – at memory location F000:FF53 there is an IRET instruction (return from interrupt). At F000:FF54 there is the beginning of the PRTSC interrupt handler. So, think about that – we have FF53 and FF54; the last nibble of the octet is either 3 or 4. Furthermore, the interrupt table at the top of memory (0000:0000) contains at position 5 (hex positions 0014 to 0017) the address of the PRTSC interrupt handler (00 F0 54 FF in little-endian notation). So to toggle print screen…if we could just change that “54” to be “53” (the address of the IRET function of the preceding interrupt vector) we’d have it done.

The code above works by using lots of tricks: the AX “accumulator” register is always zero when a DOS command file (.COM extension) runs, and the DS data segment register is what you use to manipulate memory. So, to zero out the DS register (to access the top of memory where the PRTSC interrupt is) we push AX onto the stack and pop DS off. This is equivalent to assigning AX to DS directly—but (even though it is two instructions) it is smaller (one byte each for the PUSH / POP vs. three bytes for the equivalent MOV DS, AX). This was a revelation to me—at a very basic level sometimes you really do choose size (the two instructions, that require four cycles) vs. speed (the single MOV command that uses three cycles but takes up three bytes on disk).

Then we use the XOR command to modify the data byte at offset 0x16 (that’s hexadecimal; 22 decimal). We XOR whatever was in the data byte with a 7. Let’s look at what happens:

     3      0011
XOR  7      0111
    --      ----
     4      0100

And, going the other way…

     4      0100
XOR  7      0111
    --      ----
     3      0011

By XOR’ing with a 7, we are essentially switching the values between 3 and 4.

Finally, the program uses a little trick of MS-DOS. (Remember, MS-DOS was initially written for CP/M compatibility, just do a search for INT 21 FUNC 09 for a view of how CP/M allowed strings to be printed to the screen.) For badly-written programs (which ties back to Norwhich University’s Dr. Mich Kabay’s comments on the great unwashed horde in the 80s writing any old garbage and putting it onto a machine), it wasn’t unusual for programs in CP/M simply to have a RETF (far return) without being wrapped in a CALL statement. Effectively, CP/M translated this as “return me to the operating system NOW” which effectively terminates the running program. Bill Gates (really, Tim Paterson) put in the same provision for DOS so that instead of me writing the accepted INT 20 (IBM PC ROM BIOS standard end program, took two bytes) or even more standards-based MOV AH, 4E; INT 21 (the best-practices way to end a program; but at a cost of 4 bytes; my gosh, did they think we all had 10MB hard disks??) all I had to do was a simple one-byte RETF and my program would end. I got to save at least a byte of space!

Here’s top of memory prior to doing the run:

0000:0010  XX XX XX XX 00 F0 54 FF [ ... other interrupt vectors ... ]

After running it once:

0000:0010  XX XX XX XX 00 F0 53 FF [ ... other interrupt vectors ... ]

And after running it again:

0000:0010  XX XX XX XX 00 F0 54 FF [ ... other interrupt vectors ... ]

Very amusing; to quote Homer Simpson: “Print screen goes off, print screen goes on. Print screen goes off, print screen goes on.” And all in 8 bytes (not counting the RETF).

If the machine wasn’t strictly compatible with IBM PC ROM BIOS then my little gem wouldn’t work and would in fact have a real possibility of crashing the system. Well, you can’t make an omelet without breaking a few eggs!

Team-oriented systems mentor with deep knowledge of numerous software methodologies, technologies, languages, and operating systems. Excited about turning emerging technology into working production-ready systems. Focused on moving software teams to a higher level of world-class application development. Specialties:Software analysis and development...Product management through the entire lifecycle...Discrete product integration specialist!

Leave a Reply

Your email address will not be published. Required fields are marked *

*