1

When I run a debug session using Freedos and debug.exe, I get a session like the following. I've added a description of what I saw as annotation on the image. Each step, I've printed out the stack contents. What's very confusing is why the stack is changing at all given the commands I am running - such as simple moves between registers.

step 1: move AX into DS, and mysteriously, something starts eating the stack! what gives?

MOV DS, AX

step 2: move a literal 0 value into DX, and weirdly a couple values on the stack start to change. Why on Earth is this happening?

MOV DX, 0000

... and so on. Look closely at the image to see how things change from step to step.

If anyone has a clue, I'd love to hear it.

debug session

  • 3
    This is probably off-topic here, even if you are using retro tooling. – tofro May 28 '18 at 14:20
  • What's retro about this is the reliance of interrupt service routines on the user's stack. Modern processors tend to have alternative hardware mechanisms for this, such a shadow stack pointer register that is switched to while entering in supervisor mode to service interrupts. From today's point of view, it would be bad form for the OS to have rely on the user program maintaining a proper stack pointer register and adequate stack space for servicing interrupts, given that a modern OS is protecting itself and other processes against malicious or accidental behaviors. – Erik Eidt May 29 '18 at 14:14
  • @ErikEidt I don't think that's enough to justify this as a "retrocomputing" question. The reason why this is happening is not "because you are using a retro OS", but because "you cannot rely on the memory below the stack pointer not changing". For example, I can imagine a "modern" OS where if those bytes are in a different page, they could go from "00" to "page not present" in between instructions (I don't know if that can happen in Windows; it would not occur to me to care because "I don't rely on the memory below the SP not changing"). – Euro Micelli May 30 '18 at 11:34
  • Sure, you don't want to rely on memory below the SP in general. However, the OP is not attempting to rely on memory below the SP, but rather understand this observed behavior relative to mere debugging. And I'm asserting that this particular behavior, due to its antiquated interrupt handling mechanism, is a "retro". – Erik Eidt May 30 '18 at 15:35
  • @EuroMicelli: Actually, modern PC platforms have made it "officially" safe for a function which doesn't use the stack or call other functions to use up to (IIRC) 512 bytes beyond the stack pointer for local variables without having to adjust SP before and after doing so, and so the fact that such usage isn't safe everywhere is verging on "retro". Further, on most modern debug platforms it is safe for code to abuse the stack pointer while interrupts are disabled, but the design of MS-DOS DEBUG isn't modern. – supercat Jun 1 '18 at 19:18
9

Note all your references to changing values are below the stack pointer, actually a free space. You are not expected to care about this area (stack grows towards lower addresses), as this is of no concern to your application.

Even if your computer is sitting at a debugger prompt and apparently is inactive, it isn't. It constantly runs through interrupt service routines, like the timer (or other peripherals) interrupt routines that constantly use stack memory, others will be the result of the debugger itself frequently looking for keypresses - What you see is simply the leftovers of these frequent activities in the free space of the stack (which is absolutely irrelevant for your application - The part of the stack your application is working with is above the stack pointer). Thus, the values you see are areas of free space that have been used and changed by such system routines, as you are sharing the stack with these routines. And, BTW, it is absolutely irrelevant what your appliction is doing in a debug step - These areas might also change if you are not even stepping through your own code.

The only thing you hopefully will never observe is values changing at and above the stack pointer or intermittent changes of the stack pointer itself because this is where your program's working memory is.

  • I guess I'm just surprised that even in this scenario, it would be necessary for applications to use memory so close to my own. I guess I was thinking it would somehow use more distant memory, sort of "outside" my memory space. – Byron Katz May 29 '18 at 19:15
  • @ByronKatz: More modern debugging tools will often avoid disturbing anything near the application's stack, but doing that requires that either the processor has a separate stack pointer for the application and the debugger, or that the debugger emulates the behavior of a virtual CPU, which in the absence of hardware support would totally dog performance [probably by at least an order of magnitude]. – supercat Jun 1 '18 at 21:02
  • @supercat this is not so much s function of the debugging tool, but rather of the OS, where the stack is, is normally not determined by the debugger. – tofro Jun 7 '18 at 18:52
  • @tofro: Debuggers often virtualize some aspects of system behavior. If the debugger virtualizes the stack, it can put it somewhere that it won't get stomped. On the 8088/8086, the only way a debugger could virtualize the stack would be to emulate instruction execution. Such a thing may be possible, but would be quite expensive. An 80386-specific debugger which is intended for use only with 8086-based code, however, could virtualize the stack much more cheaply. – supercat Jun 7 '18 at 19:51
  • @supercat I wouldn't want my debugger to put the stack somewhere else than the program stand-alone would put it - It stops being debugging once the debugger changes the behavior of the program. And I actually have never experienced one that did. Can you give a concrete example of one of those debuggers? – tofro Jun 7 '18 at 20:10
0

The cause of this change is the fact that you are using the 't' command to step through instructions. That command makes use of a CPU interrupt to regain control after the instruction completes. That interrupt stores state on the stack before transferring control to the interrupt handler. The state on the stack is what you are seeing.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.