I noticed that, whenever I started my AFD (Avance Fullscreen Debugger), even before the execution of the first command, the CX register has already some value. What can be the reason for this?
As you can see on the top left corner, CX has already 1Fh value...
I tried writing some other codes as well, and the results were the same. I also tried to Google it, but I was not able to find the exact reason.
My expected results are, the CX register must be 0000 as AX and BX are.
Generally you should write programs that don't make any assumptions about starting register values except when there's documentation saying that they're used for passing some input to your code (either a function or at program startup.)
DOS is a single-user OS without even kernel vs. user isolation, so it doesn't need to zero out registers to avoid leaking kernel data to user-space like modern OSes do. (But in Linux at least, dynamic linker code runs before your _start
unless you make a statically-linked executable, and the ABI doesn't guarantee zeroed register values. Only a valid stack pointer.)
Anyway, there isn't a good reason to assume that registers should be zero on startup. Kernel code was running just before it transferred control to your program, so unless it ran extra instructions to zero registers, they won't be zeroed.
The initial values for most registers are an implementation detail; depends on DOS version.
Tips for golfing in x86/x64 machine code links to https://www.fysnet.net/yourhelp.htm which has a table of initial register values by DOS version, in case you want to code-golf tiny .com
programs that take advantage of the starting registers values instead of assuming they hold random garbage.
Normally if you want BX to be zero, you'd run xor bx, bx
at the start of your program. For example, MS-DOS 1.25 (OEM) starts .com
programs with BX = CS. Many other versions start with it 0
, but not all.
FreeDOS Beta 7 & 8 do start .com
s with CX=0, but FreeDOS 1.00 and 1.10 MS-DOS and PC-DOS 2.0 and later's behaviour of CX = 00FFh
, presumably for compat with programs that depend on that. But DR-DOS 7 and later start with CX = CS.
So it's definitely not something you should depend on if you want your DOS code to be portable.
https://fd.lod.bz/rbil/interrup/dos_kernel/214b.html says
(for the INT 21 "EXEC" system call from DOS 2+: LOAD AND/OR EXECUTE PROGRAM):
Notes: DOS 2.x destroys all registers, including SS:SP
This is actually talking about the caller's perspective, for when the execed program exit and control returns to the parent. This is fixed in DOS 3.x and later, so you don't need to save ss:sp
in static storage, but most other regs are destroyed if I understand correctly. (Thanks @ecm).
.COM-format executables begin running with the following register values:
- AL = 00h if first FCB has valid drive letter, FFh if not
- AH = 00h if second FCB has valid drive letter, FFh if not
- CS,DS,ES,SS = PSP segment
- SP = offset of last word available in first 64K segment
- (note: AX is always 0000h under DESQview)
CX and BX don't have any documented state so that's an implementation detail.
If you'd been running a "new format" .exe
, then CX = size of automatic data segment (0000h = 64K).
How does DOS load a program into memory? agrees that AL and AH are set with drive letter status. And "exe header is read for initial register values" for a .exe apparently.