If 16-bit Windows had a single input queue, how did you debug applications on it?


After learning about the bad things that happened if you synchronized your application's input queue with its debugger, commenter kme wonders how debugging worked in 16-bit Windows, since 16-bit Windows didn't have asynchronous input? In 16-bit Windows, all applications shared the same input queue, which means you were permanently in the situation described in the original article, where the application and its debugger (and everything else) shared an input queue and therefore would constantly deadlock.

The solution to UI deadlocks is to make sure the debugger doesn't have any UI.

At the most basic level, the debugger communicated with the developer through the serial port. You connected a dumb terminal to the other end of the serial port. Mine was a Wyse 50 serial console terminal. All your debugging happened on the terminal. You could disassemble code, inspect and modify registers and memory, and even patch new code on the fly. If you wanted to consult source code, you needed to have a copy of it available somewhere else (like on your other computer). It was similar to using the cdb debugger, where the only commands available were r, db, eb, u, and a. Oh, and bp to set breakpoints.

Now, if you were clever, you could use a terminal emulator program so you didn't need a dedicated physical terminal to do your debugging. You could connect the target computer to your development machine and view the disassembly and the source code on the same screen. But you weren't completely out of the woods, because what did you use to debug your development machine if it crashed? The dumb terminal, of course.¹

Target machine

Debugger
Development machine

Debugger
Wyse 50
dumb terminal

I did pretty much all my Windows 95 debugging this way.

If you didn't have two computers, another solution was to use a debugger like CodeView. CodeView avoided the UI deadlock problem by not using the GUI to present its UI. When you hit a breakpoint or otherwise halted execution of your application, CodeView talked directly to the video driver to save the first 4KB of video memory, then switched into text mode to tell you what happened. When you resumed execution, it restored the video memory, then switched the video card back into graphics mode, restored all the pixels it captured, then resumed execution as if nothing had happened. (If you were debugging a graphics problem, you could hit F3 to switch temporarily to graphics mode, so you could see what was on the screen.)

If you were really fancy, you could spring for a monochrome adapter, either the original IBM one or the Hercules version, and tell CodeView to use that adapter for its debugging UI. That way, when you broke into the debugger, you could still see what was on the screen! We had multiple monitors before it was cool.

¹ Some people were crazy and cross-connected their target and development machines.

Target machine

Debugger

Development machine

Debugger

This allowed them to use their target machine to debug their development machine and vice versa. But if your development machine crashed while it was debugging the target machine, then you were screwed.

Comments (32)
  1. John Styles says:

    Ah, CodeView.

    Here in Britain CV is the term for résumé (Curriculum vitae), therefore the fact that installing CodeView meant that everyone's PC had a file called CV.DOC was a cause of some minor amusement (implying that the PC user was looking for a new job and was working on their CV in work time).

  2. Bob Paul says:

    I wasn't really fancy - I was on a budget, so my first IBM PC had only a monochrome adapter.  When I eventually got a graphics card, CodeView on the monochrome monitor was the most awesome debugging experience I think I've ever had.

  3. Joshua says:

    Hmmm I wonder how BC4.5 did it. I recall placing breakpoints in WM_PAINT and hitting them. To be fair I was on W95 at the time; however BC4.5 predates W95 and is 16 bit and debugs 16 bit.

    Breakpoint with call instruction to a Yield() loop should do it; but would require special compilation to put the loop where it can be reached by a near call (or the patch might not fit). Maybe there's something more fancy.

  4. 12BitSlab says:

    The first machine I worked on didn't have a software based debugger -- strictly hardware.  The console (no video) had a keyboard and a IO writer (printer with a roll of paper).  To debug, we would execute a CPU halt instruction from the keyboard.  Earlier models had an actual CPU halt button.  From there, one could look at memory by flipping switches and seeing which lights came on.  You could also view/change the contents of registers including the PC (program counter register).  One could also walk all over the Supervisor and patch that.  The Supervisor in today's world would be called the Operating System.  This was on a machine that did not use an 8-bit bite.  It used 12-bit slabs.  In a 12-bit slab, one could hold 2 6-bit alphas or 3 4-bit digits.

    The machine was an NCR Model 315.  Now you know where my "handle" came from.

    We have come a LONG way over the years.

  5. Adam Rosenfield says:

    Fascinating, thanks for the history lesson.  I remember reading some game programming books by André LaMothe in the late 90's/early 2000's and somewhere he was talking about some debugging framework he was using (or that he wrote? don't remember) of use on a secondary monochrome display.  It didn't really make sense to me at the time because I was used to using Visual Studio 6 (or so) to debug programs locally in a GUI, so why would anyone ever need another display and go through all that trouble?

  6. Henke37 says:

    So, a lot like kernel debugging these days?

  7. parkrrrr says:

    If BC 4.5 was like BC 3.1, it used the same text-mode trick as CodeView. We had a saying around my office that bugs were easier to see if they were in yellow text on a blue background. That saying derived from the fact that those were the default colors in the text-mode source code window in the BC debugger, and that single-stepping through code had a tendency to focus your attention on it.

    SoftICE also had the monochrome monitor trick. I used that well into the Windows 2000 era.

  8. pm100 says:

    At my first experience of this I had no real dumb terminal. I ended up using a psion organizer connected to the serial port. This has (had) a 'screen' of 2 16 character lines. You can pan around on a larger virtual screen but it was a true labor of love to debug using it

  9. Cesar says:

    Back then, switching to text mode and back was easy. The graphics cards didn't have a lot of state to save/restore, saving/restoring a few tens of registers would be enough to switch modes.

    Nowadays, switching to text mode and back is a LOT more complex.

    As an aside: using the serial port for debugging is still done today, mostly for embedded systems which don't even have a keyboard. And there's always the "big gun" of debugging: JTAG. With JTAG, a debugger running in a separate machine can halt the target processor and inspect its state directly, even if the target processor is deep within the operating system kernel.

  10. herbie says:

    I used the Hercules second monitor option - worked great. We also had SoftICE and it came with a pushbutton where the other end of the wire would slide into the NMI contact of one of your ISA cards. Push the button and SoftICE would take over no matter what state the machine was in.

  11. Joshua says:

    BC4.5 did it in the graphics environment.

  12. Adam says:

    @Adam Rosenfield - Could have been debugging DirectX code. In full screen exclusive mode you needed a second debug machine or separate video card to debug with.

  13. Yuhong Bao says:

    blogs.msdn.com/.../372424.aspx

    I am surprised Raymond did not mention it.

  14. Joshua says:

    Well for once Youhong Bao is completely on-topic. I'll bet dollars to donuts that BC4.5 uses one Hard Mode or Soft Mode. Since I don't have a Win3.1 system handy anymore I'm probably not going to find out which.

  15. Danny says:

    SoftIce anyone? I still have a VM setup with SoftIce in there. It's XP btw.

  16. j b says:

    Regarding debugging of embedded systems:

    I tried my hand at that, but realized soon that the most important debug tool was an analog scope (a kind of device I had seen only briefly during my student years), I decided to request transfer to another project.

    Nowadays those guys have replaced half of their debugging with use of logic analyzers with a Windows GUI. Maybe I now could have reentered the team, even though the hardcore guys still prefer the scope. I guess I am happy where I am now, at a somewhat higher level in the protocol stack.

  17. ChrisR says:

    I have been working on embedded for a while.  Debugging with a scope is pretty standard when bringing up new hardware or working at the hardware level.  JTAG is nice if you have an emulator for the hardware you are working on (I currently have JTAG emulators for two of three products I work on).  Overall I would say logging and serial consoles are the most useful.  If you don't have a console or some other way to output data from your device, JTAG is basically a must but is otherwise just a nicety.

  18. Adam Rosenfield says:

    @Adam: That seems like a likely explanation.  It was game programming, after all, and full-screen DirectDraw/Direct3D was definitely one of the major topics.  Back in those days I wasn't doing anything that complicated so I was always able to debug in windowed mode instead of fulls creen.

  19. alegr1 says:

    Don't care about days of yore, but with Visual Studio 201x I still can lock the whole session GUI by having a breakpoint in the wrong message hander. Not exactly lock, but make it impossible to move the VS (or any) window to the foreground. The whole session has to be killed by the separate admin session.

  20. OldFart says:

    @alegr1:  I did that to myself sometime in the last month or so.  I think the breakpoint was in a WM_INITMENUPOPUP handler.

  21. JM says:

    On an almost, but not entirely, completely unrelated note: the Commodore 128 had two video chips, the VDC capable of producing 80x25 text output and a VIC-II that produced 40x25 text output, befitting the machine's hybrid nature as something that was supposed to run CP/M as well as all your existing C64 software. As these were independent down to the outputs, you could hook them up to different monitors, allowing you to write software on the VDC business end that displayed on the VIC-II party end -- if you had the cash for two monitors, of course. I didn't, but I did have the fancy monitor that accepted both inputs and allowed you to switch between them, and that did come in handy for debugging graphics applications.

    [That's pretty awesome. It's like a mullet: Business in the front, party in the back. -Raymond]
  22. CuriousAboutWindowsDebuggingToday says:

    Interesting blog post: thanks for sharing! Could you please tell us how do you debug today? How is Windows debugged? How are device drivers debugged? Thanks.

  23. Wear says:

    @j b My final project for Uni involved connecting two embedded devices together. The devices themselves were debugged using serial ports but we used an oscilloscope to monitor the actual data being sent between them. That experience taught me that 'U' is a very useful character.

  24. Yuhong Bao says:

    @Joshua: I think it was selectable (it was in MSVC 1.x too I think), though there are some things that will cause the debugger to force hard mode.

  25. Neil says:

    I believe some versions of CodeView could save and restore the actual graphics pixels, thus avoiding having to switch display modes.

    My biggest beef with WinDbg is that if you accidentally paste while the clipboard is owned by the debugged process then it just hangs and you have to take over using a second copy of WinDbg with the -pe command-line option.

  26. Ship ahoy says:

    In the early 90s we had a Periscope hardware debugger which was OK, as I remember getting it access to source was a bit of a pig but it came with a beautiful turned metal casing for a big red button to break into the debugger, it felt great in the hand.  Of course it went missing and was replaced with a paper clip.

    I was lucky enough to have the second BW monitor for debugging of DOS16M protected mode apps back then too, that was a nice setup.

  27. Kiboro_too says:

    Windows did the serial debug trick from the early days. I worked on sound drivers for Win 0.8 that way back in '85.

    Having said that the first computer I used properly did multi-screen. It was a Research Machines 380Z (essentially S100 bus) and had a 40x25(?) scrolling text display, an 80x25(?) rich text (bold, reverse, underline) display and a graphics display (forget the res but fairly crap). The output for all these was merged but I quickly realised I could split them out so I had a graphics plotter which used a separate display for entering the equations. The world was a lot crapper for years after I lost that computer.

  28. BOFH says:

    @Wear: Reading off 'U' with a scope from a serial link is useful?

    C:>perl -we "printf(qq(%08Bn),ord U)"

    01010101

    Oh, I see...

  29. Yuhong Bao says:

    @Neil: I think this is because of the support in the Windows clipboard APIs for "delayed rendering". I get around this by copying to the Scratch Pad while the program is still running.

  30. Wolf Logan [Windows PTP] says:

    I remember debugging MS-DOS device drivers for graphics software on a Compaq Portable III -- it had a plasma display connected to a MDA attached to the case, and I had an EGA in the "expansion pod" connected to a colour monitor. I ran the SoftICE debugger on the plasma display while running the graphics software on the EGA. It always seemed to me that SoftICE was letting me see "inside the box", as I was staring at the actual case while I was using it.

  31. Gabe says:

    Wolf Logan: Mentioning that old gas plasma display reminds me that they used to be monochrome screens in amber because they used neon as the gas. When flat-screen TVs came out and I heard they were plasma displays, I was initially confused because I didn't think plasma could be made colored.

  32. Brian_EE says:

    I guess I should feel privileged in the embedded world - I've always had JTAG debuggers for use (ARM and DSPs made by an instruments company located in a large republic in the southern US). I get glaring looks when the SW team comes with a problem and I ask what the signal looked like on the oscilloscope. It's handy to show that they didn't program some peripheral register properly.

Comments are closed.

Skip to main content