Skip to main content

Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

i’ve found plenty of information on the technical details of old ibm pcs, but i can’t find much info for working with DOS itself other than interrupt lists. does anyone know good sources of information on this? the kinds of things i’m wondering are:

  • if dos is booted from a floppy disk, when is it actually used? can i remove it and still use most features?
  • if i manually mess with hardware features like video mode, floppy drives, interrupt controller, how should i reset them to their initial state when the program exits or uses a dos interrupt?
  • what sections of memory can COM and MZ executables safely mess with (without clobbering something important for DOS to run)?
  • can i load and unload other executables while mine is running? can i unload segments/parts of my program?
  • do MZ segments always load in order with predictable spacing? can i add an empty segment at the end of my executable to get relocations for the heap?
  • can i reserve space

if you already know the answers to any of these specific questions those would also be helpful by themselves.

(2 edits) (+3)

I can't definitely answer all of these questions, but can offer some clarification to most of them:

First, when DOS is booted from floppy, the kernel will remain in RAM, but the command shell will be unloaded when you launch a program to free up some memory. When your program exits, it will ask you to insert the dos floppy again so it can load COMMAND.COM back into memory and launch the command shell.

Any CRTC tweaking you do will be undone by a call to the int 10h set video mode function, which should restore you to a known good state. Usually this will be setting mode 3 (80x25 text mode) before exiting your program. The primary interrupt controller by default will be configured with all interrupts masked off except for the PIT, the keyboard, and the secondary PIC. Drivers and TSRs might unmask other interrupts though, so to be safe you can save the initial state of the mask register and restore it when your program exits.

For memory management, DOS maintains its own heap (really more of a stack) that will be allocated to your program on launch. COM programs will be allocated the largest contiguous chunk of remaining memory, up to and including all available conventional memory. You can then use the DOS memory API via int 21h to query how much was actually allocated to you. MZ executables specify in their header how much memory is required and how they should be loaded, but I can't speak to the specifics. Normally this will be handled by the compiler for a C program, and normal heap allocation functions can be used obtain more dynamic memory if necessary.

You can launch sub-programs also using the int21h API, but to do this you must make sure there's actually RAM left to do so. For a COM program this would involve shrinking your own program's allocated space before launching the nested program so that it actually has room to load. When the nested program exists, its ram will be free again to reallocate to yourself. Since DOS is a single-tasking OS, there's no need to worry about "competing" programs allocating ram, your running program effectively has total control of the system and could even clobber the DOS kernel and use its space if you want (though that's obviously not recommended since you'd need to reboot afterward).