V1.0b February 2, 2001

Table of Contents

  1. Overview
  2. Command Summary
  3. Opening Screen
  4. Command Description
  5. Cursor Operation
  6. Keyboard Commands
  7. Using Markers
  8. L: Load Markers F1..F4, F7..F10
  9. Display Markers F1..F4, F7..F10
  10. Transferring One Marker to Another
  11. C: Clear All Markers
  12. M: Toggle Ctrl Characters
  13. R: Reset display to 16-byte boundary
  14. S: Save Current Screen or Previous Screen
  15. F6: Set 32-bit Mode
  16. Program Notes
  17. Loading VX.EXE into memory
  18. Activating VX.EXE
  19. Esc, Alt-F4: Returning to the Previous Program
  20. Alt-U: Unloading VX.EXE
  21. System Messages
  22. System Halt Conditions
  23. Debugging VX.EXE
  24. TD286 Notes
  25. Links
  27. Copyright Notice


ViewXMS is a small (~15k) tsr designed to work with the Borland Real-mode debuggers, TD.EXE and TD286.EXE. It is not intended for use with TURBO.EXE, TD386, or TDX.EXE.

Borland debuggers provide a "Watch" feature to view the contents of variables and arrays. However, the watch feature is limited to the width of the display, and it cannot show the contents of large strings or arrays.

Borland provides an "Inspect" feature to view arrays. This allows you to scroll through an array, but it is very time-consuming to find a desired location in a large array.

Also, there is no way to save a location in the array, and the entire process must be repeated every time it is used. This wastes the programmer's time. The maximum array size is 64k, making it difficult to use this feature with large arrays, such as image processing routines.

Borland allows you to scroll through the data segment (View Dump), but there is no provision to view other areas of memory. For example, assembly language is often used in high performance, time-critical applications. However, routines that address memory outside the data segment are difficult to debug, since there is no variable name to place in the Watch Window.

A simple example is a block move routine. A program error can write anywhere in memory, but with no means to view memory, it is often difficult to verify the routine is reading and writing to the correct location.

VX.EXE can assist in debugging these programs by displaying the contents of memory anywhere from 0 to 4 GB. This allows you to display any memory address to detect overwrite problems, or quickly view an item in a large array to verify the data was written correctly.

Finally, Intel x86 processors use a segmented architecture. This places a 64k limit on arrays, which increases program complexity when larger arrays are required.

This limitation is easily overcome using Linear Addressing, which uses a Base Address and an Offset to provide access to data.

However, variable names are no longer needed, and debugging is difficult with Borland debuggers since there is no variable name to place in the Watch Window.

VX.EXE provides a solution. It can track any location in memory automatically, and confirm that data is transferred correctly.

The features of VX.EXE include:

  1. Displays up to 8 markers showing the contents of memory at different locations.
  2. Automatically updates markers using simple debug statements added to your code. See "VXDEMO.PAS" for more details.
  3. Uses a single keystroke to switch Borland debuggers to display the cpu registers in 32-bit mode.
  4. Saves the current screen or Previous screen to an ASCII file.

VX.EXE uses Herman Dullink's Flat Real Mode to display memory anywhere in the 0 to 4 gigabyte address range. Nir Sofer's TSRUNIT is used to provide the needed tsr functions.

System Requirements

  1. VGA color monitor
  2. 32-bit cpu
  3. DOS 5.0 or later
  4. Hard Disk drive is recommended, but will run from floppy (slowly)
  5. Runs in DOS Real Mode. Not compatible with V86 mode, EMM386, or Microsoft Windows.

Command Summary


    Home	Go to address 0
    End		Go to End of XMS Memory

    Down	Scroll Down
    PgDn	Page Down
    PgUp	Page Up
    Up		Scroll Up

    Left	Move Scroll Bit Left
    Right	Move Scroll Bit Right


    Alt-F4	Exit Program
    Esc		Exit if no Message is displayed on top line

    Alt-U	Unload Program from memory

    F1		Go to Marker #1
    F2		Go to Marker #2
    F3		Go to Marker #3
    F4		Go to Marker #4

    F7		Go to Marker #7
    F8		Go to Marker #8
    F9		Go to Marker #9
    F10		Go to Marker #10

    F6		Switch Debugger to 32-bit Mode

    C		Clear All Markers
    L		Load Markers F1..F4, F7..F10
    M		Toggle Mark Ctrl Characters
    R		Reset display to 16-byte boundary
    S		Save Current or Previous screen

Opening Screen

The initial screen is shown below. The left column of 8 numbers shows the memory address in hex.

The 16 bytes of data are shown in hex in the middle columns, and the equivalent ASCII representation appears in the far right column.

  HEX ADDR   |<------------- 16 BYTES OF DATA -------------->|  ASCII VALUE

  00000000 : 8A 10 74 01 F4 06 70 00 - C3 E2 00 F0 F4 06 70 00   t  p   p
  00000010 : F4 06 70 00 81 0C EE 0C - 79 EA 00 F0 21 EA 00 F0   p   y ! 
  00000020 : 33 01 C8 19 50 01 C8 19 - 40 6F 00 F0 40 6F 00 F0  3  P  @o @o 
  00000030 : 40 6F 00 F0 1D 19 30 18 - 57 EF 00 F0 F4 06 70 00  @o   0 W  p
  00000040 : 02 00 C8 19 4D F8 00 F0 - 41 F8 00 F0 0D 03 60 16     M A   `
  00000050 : 39 E7 00 F0 65 17 04 05 - 9E 03 60 16 CE D6 00 F0  9 e    `  
  Loc: 0              Scroll: 16            XMS 65,536 KBytes           VX V1.0b

The bottom line is the status bar. This shows the current location in memory, the Scroll Bit value, the top of XMS memory, and the version number.

The colors do not show up in plain ASCII, but a yellow vertical bar appears in the left address column. This is the Scroll Bit.

The Scroll Bit can be changed with the Left and Right cursors. It shows the value the address will be incremented or decremented when scrolling with the cursor keys.

Finally, the start of each 64-byte cache line is shown by hiliting the hex address column in light blue.

Command Description

Cursor Operation


    Sets the display address to zero.


    Sets the display address to the end of available memory.


    Increments the display address by the value in the Scroll Bit.


    Decrements the display address by the value in the Scroll Bit.


    Increments the  display  address  by the number  of  lines  in the


    Decrements the  display  address  by the number  of  lines  in the


    Move the Scroll Bit to the Left, stop at MSB.


    Move the Scroll Bit to the Right, stop at LSB.

Keyboard Commands

Using Markers

Markers F1..F4 are controlled by the contents of the Interapplication Control Area (ICA) in DOS, while markers F7..F10 are fixed at the value chosen by the user.

VX remembers the last active marker and returns to it when activated.

When VX is activated, the contents of the ICA are read, and markers F1..F4 are automatically updated to the new address. Refer to "VXDEMO.PAS" for details on loading the ICA.

If a marker from F1 to F4 is active, the display will change to reflect the new value in the ICA.

This allows the markers to automatically track address changes while debugging a program.

L: Load Markers F1..F4, F7..F10

An address is loaded into the desired marker by pressing the function keys, F1..F4, or F7..F10.

When a marker is visible on screen, it is hilited as follows:

Marker          Background   Text Color

ICA   F1	Black        Yellow
      F2	Light Red    Yellow
      F3	Green        Yellow
      F4	Dark Red     Yellow

USER  F7	Black        White
      F8	Light Red    White
      F9	Green        White
      F10	Dark Red     White

Note the ICA markers use Yellow text, while User markers have White text.

If two or more markers have the same address, the hilite color defaults to the highest marker value. In other words, if F1 and F7 are at the same address, the attribute for F7 will be used.

Display Markers F1..F4, F7..F10

The commands are:

      F1: Go to Marker #1
      F2: Go to Marker #2
      F3: Go to Marker #3
      F4: Go to Marker #4

      F7: Go to Marker #7
      F8: Go to Marker #8
      F9: Go to Marker #9
     F10: Go to Marker #10

If the marker address is valid, the function keys F1..F4 and F7..F10 display the address of the corresponding marker.

Since function F6 is used to switch Turbo Debugger to 32-bit mode, markers F5 and F6 are not used.

Transferring One Marker to Another

Markers F1..F4 are updated automatically when the ICA changes.

You may wish to store a location permanently at the start of a debug session. This is easy.

For example, to transfer the location of marker F1 to F7:

  1. Press F1.
  2. Press 'L'.
  3. Press F7.

Since two markers are now at the same location, the marker color will be the color of the highest marker, as described above in "L: Load Markers".

When changing from a low marker number to a higher one, verify the marker color changes when the new marker is loaded. In this example, the text will change from Yellow to White.

C: Clear All Markers

Markers F1..F4 and F7..F10 are cleared, as well as the Interapplication Control Area (ICA) in DOS, at 04F0 04FF.

See "VXDEMO.PAS" for more details on the ICA.

M: Toggle Ctrl Characters

When this option is active, spaces are hilited in yellow, and characters from $0 to $1F are hilited in light blue.

This allows you to find tabs, line terminations, spaces and other control characters in text fields.

R: Reset display to 16-byte boundary

If the display is not on 16-byte boundaries, the 64-byte cache line addresses are not hilited in blue.

Pressing 'R' resets the display to 16-byte boundaries, and the cache line hilites will appear again.

S: Save Current Screen or Previous Screen

The save screen function asks if you wish to save the current screen or the previous one. The Previous screen is the one displayed before VX was activated.

Press 'C' to save the current screen or 'P' to save the previous one.

Data is saved to the file "C:\TFIND.TXT". If you wish a different filename, just change the name and recompile.

TP6, TP7, and BP7 can be used to compile VX.EXE.

F6: Set 32-bit Mode

When you view the CPU window, the Borland debuggers display the CPU registers in 16-bit mode, as shown below on the right. The segments registers fs and gs do not appear.

    +-[-]-CPU 80486-------------es:0000 = 330D20CD--------3-[ ][ ]-+
    |VXTSR.179:  dw w32; db $26; db $8B; db $07; {|  ax 0000   |c=0|
    |2FB8:0020 6766268B07     mov    eax,es:[edi] |  bx 0000   |z=0|
    |VXTSR.181:  db $66; mov bx, ax {save original|  cx 0000   |s=0|
    |2FB8:0025 6689C3         mov    ebx,eax      |  dx 0000   |o=0|
    |VXTSR.183:  db $66; not ax {invert the bits i|  si 0000   |p=0|
    |2FB8:0028 66F7D0         not    eax          |  di 0000   |a=0|
    |VXTSR.185:  dw w32; db $26; db $89; db $07; {|  bp 0000   |i=1|
    |2FB8:002B 6766268907     mov    es:[edi],eax |  sp 0400   |d=0|
    |VXTSR.187:  dw w32; db $26; db $8B; db $07; {|  ds 2FA6   |   |
    |2FB8:0030 6766268B07     mov    eax,es:[edi] |  es 2FA6   |   |
    |VXTSR.189:  db $66; cmp ax, bx {compare origi|  ss 32BD   |   |
    |2FB8:0035 6639D8         cmp    eax,ebx      |  cs 2FB6   |   |
    |VXTSR.191:  jz @same {if they are the same, w|  ip 0000   |   |
    | ------------------------------------------- |            |   |
    |  ds:0000 CD 20 0D 33 00 9A C0 00 -  3     |            |   |
    |  ds:0008 00 00 BC 02 EF 1D 4B 01     K    |------------+---|
    |  ds:0010 38 04 56 01 38 04 4B 1C 8 V 8 K    |  ss:0402 0000  |
    |  ds:0018 01 01 01 00 02 FF FF FF         |  ss:0400 0000  |

The F6 command loads the keyboard buffer with the keystrokes needed to switch the debugger to 32-bit mode, and display the CPU in full-screen mode. The original code view is restored, and VX exits to the debugger.

Since your finger is still on the F6 key, you can press it again to switch the debugger to View CPU Mode.

The display will be full-screen. The registers are now 32-bit, and fs and gs both appear in the list.

    +-[-]-CPU 80486-------------es:0000 = 330D20CD--------3-[ ][ ]-+
    |VXTSR.179:  dw w32; db $26; db $8B; db $07; {|eax 00000000|c=0|
    |2FB8:0020 6766268B07     mov    eax,es:[edi] |ebx 00000000|z=0|
    |VXTSR.181:  db $66; mov bx, ax {save original|ecx 00000000|s=0|
    |2FB8:0025 6689C3         mov    ebx,eax      |edx 00000000|o=0|
    |VXTSR.183:  db $66; not ax {invert the bits i|esi 00000000|p=0|
    |2FB8:0028 66F7D0         not    eax          |edi 00000000|a=0|
    |VXTSR.185:  dw w32; db $26; db $89; db $07; {|ebp 00000000|i=1|
    |2FB8:002B 6766268907     mov    es:[edi],eax |esp 00000400|d=0|
    |VXTSR.187:  dw w32; db $26; db $8B; db $07; {|  ds 2FA6   |   |
    |2FB8:0030 6766268B07     mov    eax,es:[edi] |  es 2FA6   |   |
    |VXTSR.189:  db $66; cmp ax, bx {compare origi|  fs 0000   |   |
    |2FB8:0035 6639D8         cmp    eax,ebx      |  gs 0000   |   |
    |VXTSR.191:  jz @same {if they are the same, w|  ss 32BD   |   |
    | ------------------------------------------- |  cs 2FB6   |   |
    |  ds:0000 CD 20 0D 33 00 9A C0 00 -  3     |  ip 0000   |   |
    |  ds:0008 00 00 BC 02 EF 1D 4B 01     K    |------------+---|
    |  ds:0010 38 04 56 01 38 04 4B 1C 8 V 8 K    |  ss:0402 0000  |
    |  ds:0018 01 01 01 00 02 FF FF FF         |  ss:0400 0000  |

You can use the F8 key to single-step through the code and watch the contents of the registers change.

Pressing the F6 key cycles through the Watch window to the normal code view, then back to the CPU view.

If you activate VX and press F6 again, the registers stay in 32-bit mode, but the View CPU window toggles to the small version shown above.

Program Notes

Loading VX.EXE into memory

When loading in memory, VX.EXE performs the following checks:

  1. Verifies you have a color VGA monitor. If not, halt.
  2. Checks to see if VX is already installed. If so, halt.
  3. Prints a short message showing the activation and unload keys.
  4. Activates Flat Real Mode to do a binary search for the highest available XMS memory address.
  5. Installs the tsr and returns control to DOS.

If no errors are detected, VX prints the following message:

Installing ViewXMS.
Press CTRL, then Left Shift to activate.
Press Esc to exit, Alt-U to remove.

Activating VX.EXE

To activate VX.EXE, press Ctrl, then Left-Shift.

When the hotkey is activated, VX.EXE initializes itself by performing the following steps:

  1. Saves eax, ebx, ecx, edi, edx and esi on the stack.
  2. Activates Flat Real Mode.
  3. Clears the keyboard buffer.
  4. Saves the Previous Screen to a file named 'vxscr.$$$' in the current directory.
  5. Turns off the blink bit in the VGA display.
  6. Saves the Previous Cursor state and turns it off.
  7. Adjusts the display to the number of lines in the Previous display.
  8. Clears the VGA screen.
  9. Updates markers F1..F4 from the ICA.
  10. Waits for a user keystroke while displaying the contents of memory.

Esc, Alt-F4: Returning to the Previous Program

To return to the Previous Program, VX.EXE performs the following steps:

  1. Disables Flat Real Mode.
  2. Restores the Previous Screen.
  3. Restores the Previous Cursor.
  4. Clears the keyboard buffer.
  5. If the user has requested 32-bit mode, VX.EXE stuffs the keyboard buffer with the keystroke sequence needed to put the Borland debugger in 32-bit mode.
  6. Restores eax, ebx, ecx, edi, edx and esi from the stack.
  7. Returns to the Previous Program.

Alt-U: Unloading VX.EXE

To unload from memory, VX.EXE performs the following steps:

  1. Disables Flat Real Mode, restores the Previous Screen, restores the Previous Cursor, and clears the keyboard buffer.
  2. Checks to see if another tsr was loaded after VX.EXE. If so, it displays an error message and follows the normal exit back to the previous program. VX remains in memory.
  3. If no tsr was loaded, VX removes itself from memory.

There is currently no provision to detect ordinary DOS programs that were started after VX.EXE was loaded. Unloading VX.EXE while another program is running will probably require a reboot.

Use ALT-U only from DOS.

System Messages

VX uses the top line to communicate messages to the user. If a key was pressed accidentally, Esc will abort any command and clear the message.

Note: Esc does not close VX while a message is visible. However, it will clear the message, and pressing Esc a second time will exit to the previous program.

System Halt Conditions

VX will terminate if it cannot read or write to the disk.

This will cause problems if other programs are loaded after VX. However, a disk failure is fatal, so terminating VX may be the best course of action.

Debugging VX.EXE

Due to a bug in Dullink's FLAT implementation, VX.EXE cannot be debugged while displaying addresses greater than 64k.

A far call used in the tsr apparently causes Dullink's FLAT_INSTALL to generate a corrupt Global Descriptor Table. This causes a reboot.

Curiously, this only happens while VX.EXE is being debugged in a debugger.

If VX is installed before the debugger is loaded, the tsr version of VX can be activated at any time without exhibiting this problem.

But this means Dullink's FLAT code cannot be used with overlays or procedure variables. There is no way to debug the code!

I am working on a solution and will post the updated version when available. But if you already have a solution and can share it, please contact me at

Michael R. Monett, add.automation@sympatico.ca

TD286 Notes

The Borland real-mode debuggers occupy a great deal of memory, leaving little to debug your own program.

TD286 is an excellent real-mode debugger. It handles Pascal, C, and assembly programs.

It runs in protected mode in XMS, and needs only 79k of base ram. This leaves much more memory for your program.

If your program uses XMS, you will find that TD286 allocates all but 64k to itself. You can correct this by adding a file named "CONFIG.286" to the root directory of the current drive.

Add a single line to the file as follows:


This forces TD286 to use only 2 megs of XMS, leaving the rest for your program. (This is not documented in BP7, but is described in the TDBUG.HLP file in TP6.)

TD286 also will not load above 16 megs in XMS. If you need a large ramdrive and SmartDrive, you may exceed the 16 meg limit.

Franck Uberto's XMSDSK.EXE is an excellent ramdrive replacement, and can load at the top of XMS. It is available at the link shown below.


Herman Dullin's FLAT distribution http://www.nondot.org/sabre/os/S5ProtectedMode/FLAT.ZIP

Nir Sofer's TSRUNIT v1.10 http://ftp://ftp.cdrom.com/.2/simtelnet/msdos/turbopas/tsrun110.zip

Franck Uberto's XMSDSK.EXE http://ftp://ftp.cdrom.com/.2/simtelnet/msdos/ramdisk/fu_rd19i.zip


The usual disclaimer applies. You are responsible for any problems using this software. Back up your system before installing it.

Nir Sofer's TSRUNIT is one of the best I have used, and it has performed flawlessly from the start. But due to to the unusual combination of Flat Real Mode in a tsr, you may experience incompatibilities with other tsr's or with some programs.

Be sure to save any files before activating VX in your editor, and carefully check for any incompatibilities with the software you normally use.

Due to the wide variety of software and hardware in use, I doubt I can be of any assistance helping solve problems with your software or hardware.

Any comments are welcome. If you would like to be notified of future updates, you can reach me at

Michael R. Monett add.automation@sympatico.ca

Copyright Notice

Copyright (c), 2001, Michael R. Monett

The original url is http://www.oocities.com/mrmonett/index.htm

Copies may be made for any purpose providing this copyright notice and the original url are included.