The context is that I'm calling DOS interrupts from DPMI using int31 / ax=0x300, and you have to tell it what stack you want the real mode call to have. By default you get a small stack of about 20 bytes which isn't nearly enough. Experimentally I've found that 128 bytes is still too small and 512 seems to work, but it'd be nice to have a definitive source as to what it should be.
1 Answer
I’m not aware of any official documentation of MS-DOS’s stack requirements for interrupt 0x21; in any case, that wouldn’t paint the full picture since any TSR or driver hooking the interrupt could add to the required stack size without providing any means of determining how much extra room it required.
However the DPMI 1.0 specification says the following in its section on stacks and mode-switching (also available on DJ Delorie’s site):
The real mode stack is also provided by the DPMI host, and is usually located in the DPMI host data area allocated by the client prior to its initial switch into protected mode. The real mode stack is at least 200H bytes in size and is always located in locked memory. Interrupts that are reflected to real mode, as well as calls to real mode interrupt handlers or procedures via Int 31H Functions 0300H, 0301H, or 0302H, will use this stack.
So as far as the DPMI specification is concerned, the answer is 512 bytes. This was already the case in version 0.9 of the specification:
The DPMI host will provide the client with a real mode stack that is at least 200h bytes in size and will always be locked. Interrupts that are reflected into real mode, as well as calls made using the translation services, will be reflected on this stack. DPMI hosts will not automatically switch stacks for hardware interrupt processing in real mode since DOS performs this function automatically.
Your findings suggest that at least some DPMI implementations provide a (much) smaller stack; Ralf Brown’s Interrupt List agrees, saying “DPMI will provide a small (30 words) real mode stack if SS:SP is zero”. I imagine there’s a reason behind the 512-byte minimum in the specification, so I take this as confirmation of your findings: the default stack can’t be relied upon (whatever the specification says), but having the caller provide a 512-byte stack should be sufficient.
Typically you’d use a DOS extender which would provide a protected-mode interrupt 0x21 handler and take care of all this for you, but presumably that’s not applicable here.
-
2Interesting; I was going with Ralf Brown's Interrupt List, which says this about int 31 0300:
DPMI will provide a small (30 words) real mode stack if SS:SP is zero.
I was definitely observing stack corruption with the default stack and switching to a larger stack made it go away. Aug 20, 2022 at 8:33 -
2Yes, I gathered from your question that some implementations don’t provide as much as the spec says! The purpose of my answer wasn’t to suggest that you should rely on the default; rather, that since the spec relies on a 512-byte stack (or larger), presumably there’s a reason for that and you should provide a 512-byte stack if you’re going to provide your own (which also matches your findings). Aug 20, 2022 at 10:15
-
1It might be helpful, that DOS simply can not guarantee any maximum stack usage, as DOS relies on external drivers, for all devices, which it has no control over - at least not in terms of stack usage.– RaffzahnAug 20, 2022 at 10:33
-
1I had also misremembered '30' as '20' and 'words' as 'bytes', so that didn't help... Aug 20, 2022 at 10:56
-
1@Raffzahn: Same basic problem. If you don't define a value; the value will be set to some arbitrary value by pre-existing application code and later drivers won't work.– JoshuaAug 20, 2022 at 20:57
fs
andgs
? Isn’t DOS supposed to run on an 8088?int21
interrupt under DOS 6.22. 90 bytes were used. Normally, this should not differ for different functions because DOS has its own stack and modifies theSS:SP
registers when entering the interrupt. However, some loadable drivers may overwriteint21
, push data on the stack and call the originalint21
. If you have multiple of these drivers, the stack consumption may increase a lot.