home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Large Pack of OldSkool DOS MOD Trackers
/
funk108a.zip
/
DOS32V30.ZIP
/
DOS32.DOC
< prev
next >
Wrap
Text File
|
1995-06-14
|
48KB
|
1,276 lines
DOS32 Version 3.01
Released on 14 June 1995
A 32 bit DOS extender package
Copyright (C) 1994 Adam Seychell, All Rights Reserved.
This document should explain everything about the DOS extender
DOS32 V3.01. This program may only be of use to people who have some
knowledge of assembly language programming. However, I have tried to
make this document easy for a beginner to understand. Anyone who can
no longer tolerate programming with pathetic 64Kb segments or is sick
of the 640Kb barrier and wants to program using the full power of
their computer then use DOS32 for protected mode programming.
AGREEMENT
This program is free software only and may not be sold other than
the cost of the disk or physical handling. The use of this program is
entirly at the users risk. In no event will the author be liable for
any damages, including any lost profits, lost savings or other
incidental or consequential damage arising out of the use or inability
to use the program ,or for any claim by any other party. This program
is distributed WITHOUT ANY WARRANTY.
You can redistribute it only in the same form as you have
received it and all files must be left unmodified. The exception to
this rule is if you choose to develop an application that requires the
file DOS32.EXE then you may freely distribute it with the application.
Only with my permission can you take separate files from this package
and include them in your productions.
If you are releasing the source code to your program then it may
require DOS32 for compiling. Under these circumstances you may include
an unmodified copy of the entire DOS32 package within your program.
Use of the DOS32 dos-extender in any commercial software requires
written permission from the author.
Of course I have no real control on what people do with it so I
am just relying on your honesty. So please, help support free
software.
* * *
The DOS32 project has been developed entirely in my spare time
and I've been slowly working on it for over two years now. It's only
fair for me to ask that ALL programs that use the DOS32 dos-extender
must include full credit for it's use. If you really like this
program then I would also enjoy receiving a postcard from you.
Anyone may buy a copy of the complete source code to DOS32.EXE
for a fee of $40 Australian. The source code is about 180KB in size
and may be compiled with either MASM (Microsoft Macro Assembler) or
TASM (Turbo Assembler), it is also very well commented and so it
should be easy to follow and learn from.
Address all correspondence to the author at the following
address;
Adam Seychell
16 Avion Place
Westmeadows, VIC. 3049
AUSTRALIA
internet: s921880@minyos.xx.rmit.edu.au
Please ensure you enclose your return address!
If you wish to purchase the DOS32 source code then write out your
cheque in the name of Adam Seychell.
WHAT IS A DOS EXTENDER ?
The 80386 has been around since 1987 and to this day DOS is still
running in real mode. Since nobody has bothered to design a protected
mode DOS, programs called 'DOS extenders' were written. A DOS extender
is basically a program that will switch the CPU into protected mode so
that it can then execute a protected mode application under DOS. If
you don't know the difference between real mode and protected mode
then have a go at reading the file PMODE.DOC or better still get a
proper book before reading to much further. I think that it is much
easier to program in protected mode than in real mode ( Intel 8086
architecture ) because you can use only one big segment for the entire
application.
You could say a DOS extender is a separate program that handles
all the setting up needed for protected mode under DOS. You let the
DOS extender worry about all of the protected mode initialising. So
you write programs in plain and pure protected mode.
Since DOS runs in real mode ( or V86 mode ) a protected mode
program can no longer execute DOS calls directly. The DOS extender
should have services that allow protected mode programs to call real
mode code and will either enter V86 mode or return to real mode when
doing so. Usually a DOS extender has many more services than just real
mode calls. For example, setting interrupt vectors, memory allocation,
disk I/O routines and possibly a debugger.
DOS32 Introduction
DOS32 V3.0 is a public domain 32bit DOS-extender package for
the development of true 32bit DOS executable. The actual extender is a
real mode DOS executable called DOS32.EXE. This tiny 8K file is the
heart of the hole package. DOS32.EXE will initialise protected mode
then load and execute a custom 32bit executable. To make one of these
32bit executables you must use the linker, DLINK, which is also
distributed in this package.
My main aims when developing DOS32 was to make a DOS-extender
that is very easy to use, has powerful features and small in size. I
have also tried to make the extender as close as possible to
programming under conventional real mode DOS, and yet have full 32bit
power. This should make it easier for people to start programming in
protected mode. The debugger that is distributed with DOS32 should
also help you become more familiar with the workings of protected
mode. I have released my work so people can stop programming in a 8086
architecture, a CPU produced back in 1978.
What is DLINK?
The program DLINK is a linker supporting the Intel standard
Object Module Format (OMF). DLINK is distributed with the DOS32
package and is required to produce the customary 32bit executable file
that's loaded by DOS32. The main difference between DLINK and a
conventional DOS linker such as Borland Turbo Linker (TLINK.EXE) or
Microsoft Link (LINK.EXE), is that DLINK produces a special executable
format made specifically for flat memory model programs. When DLINK is
first ran it will begin processing the object modules specified on the
command line. The information inside the modules is used to create a
32bit executable file of your application, which may simply be
executed under DOS. Exact details of the loading process are explained
later in this document.
Here are some of DOS32 main features
* Complies with the following specifications;
Dos Protected Mode Interface ( DPMI v0.9 )
Virtual Control Program Interface ( VCPI v1.0 )
Extended Memory Specification ( XMS v2.0 and v3.0 )
Int 15h Top-Down extended memory management
* Unlimited executable size.
* Paged memory enabling a true flat memory model.
* Functions for allocating/freeing memory and DMA buffers.
* Contains a complete set of 32bit DOS file I/O services
( open/close/create/read/write/chdir/rename, ect).
* Services for interfacing with Real Mode programs.
* Capable of terminating and staying resident.
* Uses only 42K _total_ memory and requires just 8K of disk space.
* Distributed with a debugger , C library and linker.
Minor features
* Supports up to 4Gb of RAM
* Executable can be compressed
* Can run with zero extended memory
* Handles all errors during initialising
* Load time selector fixups in executable.
* Not a single 4KB block is wasted on the machine
* DOS32.EXE can be integrated in the main .EXE file
* Hooks XMS driver to stop disabling of the A20 gate.
* Detects VCPI even with Microsoft's EMM386.EXE NOEMS
* No overhead on hardware interrupts (expect under DPMI)
* Runtime termination for CPU exceptions 0,1,3,6,13 & 14
* Uses VCPI if available even when a DPMI server is present
* Hooks INT 23h for correct Ctrl+C/Ctrl+Break termination
* Fast starting and exiting. Less than 0.3 sec total on a 386SX16
* Guards from returning to protected mode from a real mode switch
when under a XMS or raw systems and the 386 is in V86 mode.
* Stops DOS32 trying to be loaded into upper memory because the
system resets when doing so.
The DOS32 Applications Programming Interface
The DOS32 extender supplies many useful functions for the
application to use. The complete list of each service and programming
details are described in the file API.DOC. I've put all the API
documentation in a separate file so it may be printed as a handy
reference. ( 65 lines per page).
DOS32 OPERATION
This is the main section of this document and will explain the
workings of DOS32.
This is a flat memory model DOS extender. Flat memory means that
the entire application is operating in a single block of linear
memory. You may think of it as the application gets loaded into memory
in one hit and is located somewhere in the CPU address space. This
location is called the program base address since it represents the
first byte of the program. The CPU is set up for data and code type
segments with their base addresses equal to the program base address.
However, as these two segments are on top of each other in memory they
can effectively be treated as one segment. This allows the
applications data variables and code to be mixed together. The memory
map below may help you understand what's happening.
Figure (1). The CPU memory map demonstrating a protected mode
application loaded into memory.
┌─────────────────────┐ FFFFFFFF
│ │
│ │
░░░░░░░░░░░░░░░░░░░░░
│ │
│ │
│ │
├─────────────────────┤
│ 32bit application is│
│ loaded in here │
├─────────────────────┤ <-program base address
│ │ (can be anywhere above 1Mb )
│ │
│ │
├─────────────────────┤ 100000h
│ ROM area │
├─────────────────────┤ C0000h
│ video memory map │
├─────────────────────┤ A0000h
│ │
│ 640K base RAM │
│ │
└─────────────────────┘ 0
The program's data and code segment limits are 4GB in size. This
means the largest OFFSET address (relative to the program base
address) can range from 0 to FFFFFFFF. An offset of FFFFFFFF will not
address memory above 4Gb but rather rap around so it will address
memory somewhere below the program base address. Therefore it's
possible to access the entire CPU address space with only a single
32bit offset. It also means there is no need for your programs to ever
again use multiple segment registers. These are the reasons why I
wrote DOS32.
DOS32 sets up three segments for the application. As explained
above, two of these are the applications code and data segments. The
third segment is another data segment with a fixed base address of
zero and may be used to access physical addresses such as video
memory, BIOS data area, ect. Most of the time the application will
never need to use this secondary data segment because the entire CPU
address space can already be accessed from the programs data segment
using 32bit offsets. The selector value of this zero based data
segment can be obtained from function AX=EE00h INT 31h. The program
base address value can be obtained from function AX=EE02h INT31h (see
API.DOC for details).
If you are unfamiliar with protected mode, descriptors and
segments then have a go at reading the files PMODE.DOC and PMODE2.DOC.
These files will explain some basics of protected mode operation.
So basically there are three different segments available to the
application, and all have limits of FFFFFFFF.
* data segment
* code segment
* zero base data segment
Please note that the first 1 MB of linear address space is mapped
to the lower 1Mb of physical address space. This means that accessing
locations 0..100000h will actually access the first megabyte of
physical memory. This allows the application to access physical memory
anywhere in the lower 1 MB. The offset address relative to the program
segment can be calculated to point at any location in the first 1Mb of
physical memory.
offset = Physical address in first MByte - Base address of segment.
Alternatively you can also use the zero based segment to access
memory in the first megabyte. In this case if the memory is below 1MB
then the Offset = linear = physical. You will probably only need
physical memory locations to access the video memory (i.e 0A0000h -
0BFFFFh). If your program dos not need the zero base segment then you
can ignore this selector value and keep all of the segment registers
( DS,ES,FS,GS,SS ) loaded with the program data selector. This is what
makes protected mode so powerful, you can access all of your
data,code, video memory or whatever just by using the 32bit offset.
If you are still not clear on what I am saying here then try having a
look the programming examples distributed with this package.
When the application is first executed at the program entry point
the CPU registers will hold the following values. All data segment
registers, DS,ES,FS,GS and SS, will contain the programs DATA
selector. CS will contain the programs CODE selector. EIP will point
to the program entry address. ESP will point to the last dword of the
defined stack (as explained below). EAX,EBX,ECX,EDX,EDI,ESI,EBP and
FLAGS registers are all undefined and may contain any value.
Executable format and loading process.
The information here will explain how DOS32 and DLINK work
together and exactly what happens when the executable is first ran
from DOS to when the application's first instruction is executed.
Please note that it is not essential for you to know these details but
will be described here for those of you who are interested.
File format of a DOS32 executable (.EXE file produced from DLINK)
Offset Size Description
─────────────────────────────────────────────────────────────────────
0 n A stub loader or DOS32.EXE of n bytes
n+0 4 Signature "Adam"
n+4 2 DLINK version
bit 15 = 0 executable image is not compressed
= 1 executable image is compressed.
bits 0..14 hold the DLINK version in packed BCD format
n+6 2 Minimum DOS32 version required (packed BCD)
n+8 4 Number of bytes remaining after the stub file.
The entire .EXE file size (after linking) will be equal
to this value plus the stub file size.
n+0Ch 4 Start of 32bit executable image relative to the 'Adam'
signature.
n+10h 4 Length of executable image ( see below ).
n+14h 4 Initial memory required for application. This value
must be larger than the size of the 32bit executable
image.
n+18h 4 Initial EIP
n+1Ch 4 Initial ESP
n+20h 4 Number of entries in selector fixup table. Each entry
in the table contains a 32bit offset relative to the
start of the executable image of a 16bit WORD that must
be set to the programs data selector at load time. The
table immediately follows the executable image.
The 32bit executable image (application binary data) can start
anywhere after this point (offset n+24h in the .EXE file).
--- more entries can be added in future ----
At the front of the .EXE is the stub loader or DOS32.EXE file and
must be a normal DOS executable ( i.e start with a 'MZ' signature ).
When the .EXE is executed, DOS will only load and execute the 'MZ'
executable at the front of the file and ignore the rest of the file.
The stub loader is a small program that will simply execute DOS32.EXE.
I have distributed a sample stub loader, STUB.ASM. This actual program
is stored internally in DLINK and is automatically used as the stub if
the -S option is not used. See later in this document for more
information about the -S switch.
When the program DOS32.EXE is executed it will first initialise
for protected mode and try an load in the 32bit application. It does
this by first checking at the end of the it's self for the 'Adam'
signature. If found it will then assume that it is a DOS32 32bit
executable and read the rest of the header and begin loading the
application it into memory. If no 'Adam' signature was found it will
then look at parent program which had executed DOS32.EXE. If the
parent program has the 'Adam' signature then it will begin loading the
executing the DOS32 executable. If the parent does not contain the
signature then the following error will be displayed.
DOS32 Version 3.00 32bit DOS-extender and loader
Copyright (c) Adam Seychell, 1994. All rights reserved.
File name: C:\DOS32.EXE
Error: Bad DOS32 executable
With this set up it allows DOS32.EXE to be used in place of the
stub loader. If a stub loader is used, and the user runs the .EXE, the
stub file will be executed which in turn will execute DOS32.EXE. DOS32
will then begin it's work, by first initialising for protected mode
operation and allocate a memory block for the application. The
executable image is then loaded into the memory block followed by
applying the selector fixups. Finally the stack pointer (SS:ESP) and
instruction pointer (CS:EIP) are set to finally start the application
up and running.
PROGRAMMING
The section explains, in general, on how to write protected mode
applications. It will explain about the initial stack, entry point,
selectors, segments definitions and examples of basic ASM file
structure.
Segment Definitions
There may be some confusion with segments defined in the ASM file
to the segments set up by the CPU. If you cannot grasp all this
segment stuff then don't worry. It's only useful to know if you want
to understand how the programs are stored in the executable.
In real mode if you declared a segment that is not grouped to the
main segment then a segment register must be loaded with the segment
value if any data/code is to access it. For example, if the
application had more than 64KB of code then multiple code segments
would need to be defined and far calls would be required to call
across the segments. The CPU segment registers have to be altered each
time a the CPU accesses a new segment.
In a flat memory things work completely different. Segments
defined in the ASM file (or in modules from a C compiler) have nothing
to do with segments defined in the CPU descriptor tables. As described
earlier, flat memory is when only one segment in memory exists for the
entire application. Segments defined in the ASM file are like
secondary segments or sections within the actual program segment in
memory. The object modules ( OBJ files) contain information of all the
segments that have been defined in the source code. The linker will
place all the code/data from a particular segment name and group it
into one section in the program segment in memory. For example, all
data/code that has been defined in the segments named 'blabla' will be
grouped to together when stored in the executable.
The Object Module Format ( format of OBJ files ) are capable of
containing all sorts of information about a segment definition. Some
of these include public or private, Alignment in memory and Group
definitions. However for flat memory most of them can be ignored.
Rules on how DLINK handles segments.
* DLINK can support up to 100 segment definitions.
* Each segment is automatically made public. The public field in
the segment definition is ignored.
* The segment alignment may be set on the DLINK command line. The
alignment field in the segment definition is ignored. for example
* The occurrence of each segment definition in the executable will
be same order as they are defined in the object modules.
* Each segment will automatically be grouped together. The
assembler GROUP directive is ignored.
* The code/data defined in segments of the same name will be next
to each other in the executable.
It is possible to define data that is not initialised. In this
case the actual segment size greater than the total size of code and
data that is defined in it. In assembler, non-initialised data can be
defined with the ? operator. The following two examples will define a
1Kb array of data that is not initialised to any value.
My_Array DB 1024 DUP (?) ; Assembly language
char My_Array[1024]; /* C language */
The non-initialised data does not matter what information it
contains when the application is first loaded. Therefore if the end of
the executable contains non-initialised data then there is no need for
it to be loaded into memory and therefore stored in the .EXE file.
DLINK takes advantage this and will not include any non-
initialised data in the executable file which has been declared at the
end of the program segment. This is how the initial stack area is set
up. A segment is defined with an array and the stack pointer will
point to the last dword of the segment.
Defining the program entry point
The entry point of the program is defined exactly the same way as
writing a conventional assembler program. The start address will equal
to the label at the assembler END directive. For example, the
following code shows how to identify a program's starting instruction
with the label 'start'.
.CODE ; define code segment using
; quick segment definitions.
start:
..
..
..
END start
Please note that the program entry point will only be set to the
first module to contain a starting address. Starting addresses defined
in following modules will be ignored and the linker will report with a
warning message. The program eventually terminates with INT 21h
AH=4Ch, just as in good old DOS.
Defining the initial stack
When the program is first loaded the initial stack area is
defined by the last segment with it's class name equal to 'STACK'. The
initial value of ESP will point to the last dword of this segment.
Please also note that DOS32 should have a stack size of 128 bytes to
play with. Add to this what ever stack your program is going to use.
Example: To define a 128Kb stack
My_Stack SEGMENT 'STACK'
DB 20000h DUP (?)
My_Stack ENDS
If you are using the assembler quick segment definitions ( e.g .model
.code .data .stack ) then the stack may be defined with the assembler
directive .STACK [size].
Reading the program data selector
In a real mode program the segment value could be obtained by
referencing a segment name. E.G MOV AX,_TEXT will load AX with
the real mode segment value of the _TEXT segment. In protected mode
only selectors are used so loading AX with a real mode segment value
is useless not to mention impossible if it's above 1MB. Whenever a
segment name is referenced (like in the above instruction ) the value
of the programs data selector is read. It does not matter what segment
name or group definition is referenced, the value read will *always*
be the programs data selector. This feature is handy for interrupt
handlers as the program data selector may be required. For example,
the following code will set both DS and FS segment registers to the
programs data selector.
First_Seg SEGMENT
First_Seg ENDS
The_Seg SEGMENT
mov ax,The_Seg
mov ds,ax
mov ax,First_Seg
mov fs,ax
The_Seg ENDS
If you are using the assembler quick segment definitions ( e.g .model
.code .data ) then you may reference the data selector using '_DATA'.
This is because the .Model directive automatically defines _DATA as
the name of the data segment.
General Assembly Language file structure
For most applications the programmer will only ever need to use
the assembler quick definitions directives for setting up segments.
Both TASM and MASM 6.x support the new FLAT memory model types and so
have no problems compiling flat memory 32bit code. Flat memory model
programming is easy since there is no limitation on what goes where.
For example you could write all the code in the .DATA segment and
place all data variables in the .CODE segment.
Below is an example of a basic ASM file;
.386
.MODEL FLAT
.STACK
.DATA
..
.. code/data
..
.CODE
...
... more code/data
...
Start:
...
...
... code and data can go anywhere
...
END Start
The above example will create a starting module since it contains a
symbol after the END directive. The .STACK should only need to be
defined in one module only. If it's defined more than once then the
linker will added all the stacks together to form one large stack area
(assuming the assembler greats the same names for each stack segment
definition). If other modules are to be linked with the above example
then they should not define a stack and/or a starting point.
For example;
.386
.MODEL FLAT
.CODE
...
... code/data
...
END
It couldn't get any simpler, really.
32bit Programming Notes
If you are new to 32bit assembly then there are a few important
things you need to know. First off, all memory refrences should always
be using 32bit addrssing modes instead of 16bit addressing modes. For
example, the instruction MOV AL,Varible[BX] is using 16bit addressing
and consequently will have a 16bit displacment value. If this varible
is located above 64Kb then the assembler cannot fix up the correct
address. The above instruction should be MOV AL,Varible[EBX].
Secondly, avoid pushing and poping 16bit registers on the stack
becuase these may take the stack pointer out of dword alignment. ESP
should always be kept aligned on a 4 byte boundary or else your
program may run slower. This is because in 32bit mode, the stack
transfers in double words and the CPU will take extra clocks cycles
for every misaligned memory reference.
The Segment Registers (i.e DS,ES,FS,GS,CS) are always stored as
dwords on the stack in 32bit mode.
USING THE LINKER
Since the DOS32 package is mainly for assembly language
programming I will assume you are familiar and have used a
conventional linker before. Remember DLINK has been designed
specifically for flat memory model programs so there is no need to
worry about all the modules and segments combining to produce one
large executable. If you wish to stop DLINK while it is processing
then press the CTRL+BREAK keys, it then should return to the command
prompt.
DLINK is controlled entirely by the command line so you will need
to know what each command line switch does. The format of the command
line is;
DLINK OBJ file list [, EXE file] [,MAP file] [, LIB file list]
The OBJ file list is a list of the Object Modules that DLINK is
required to link. Each file name is separated by spaces. If the
executable file name is not specified then it will be equal to the
name of the first OBJ file. The default file name extension of the
Object Module file list and executable file are .OBJ and .EXE
respectively.
The MAP file is a small text file that the linker creates showing
information of all the segments defined in the modules. I included
this feature for compatibility with conventional linkers. If no MAP
file is specified the file is not created.
The LIB file list are library files that the linker is required
to process. The format of these files must be in the Microsoft Library
file format (.LIB extension). DLINK will link ALL object modules
contained in the library file. Even if the modules are not required by
the program DLINK will still include them in the executable.
DLINK will also accept command line response files. The response
file is a text file containing the input DLINK expects on the command
line and has the exact same format as the Turbo linker (TLINK.EXE) or
the Microsoft linker (LINK.EXE) response files. All response files
specified must precede the name with an @ character. The response file
can be used to overcome the 128 character limit of the command line or
is sometimes used by compiler make utilities.
DLINK Options
The linker options can go anywhere on the command line and must
start with - or / characters. If the environment variable
"DLINK_OPTIONS" is available then DLINK will set options contained in
this environment string. You can use this environment variable to hold
frequently used options. Below is a description of each option.
Option Description
@xx Where xx is the file name of a response file. Multiple response
files are allowed and can be placed anywhere on the command line.
/v Verbose linking information. This will display all sorts of
information that the linker is currently processing.
/m Create MAP file even if none is specified on the command line.
/L<path1>[;<path2>][;<path3>]
Specify library search paths. This switch tells the linker to
also search in the directory <path> when loading library files
specified on the command line.
/c Case sensitive symbol matching. All external symbols that are to
be matched with public symbols in other object modules will be
compared case sensitive. When this switch is not used, matching
is case insensitive.
/Sx Use alternate stub file x. The stub loader which is placed at the
front of the executable file will be the file x. If x is not
specified then DOS32.EXE will be used as the stub loader. If no
file extension is specified the extension '.EXE' will be used.
For example, dlink -Sstuber will use the file stuber.exe as the
stub loader. When this switch is not used, a default stub loader
is used.
/p Ignore checking of the same symbol name defined more than one
object module. Setting this switch may speed up the linker when
processing more than a few hundred symbols but then has the risk
of linking in the same symbol name more than once.
/A=N Set segment alignment to N. The starting address of the data
defined in each segment definition will be aligned on a N byte
boundary. Valid values of N are 1,2,4,8,16,32,64,....,2048,4096
If this switch is not used then the segment alignment defaults to
a four byte boundary (/A=4) which is all that is necessary for
the 386,486 and Pentium CPUs.
/C Compress final .EXE. This option will tell the linker to compress
the 32bit executable image in the .EXE file. The stub loader,
header and fixup table are kept uncompressed. See reference 10
for the algorithm I used. On average the compression will
produces files about 1.2 to 1.5 times that of the ZIP
compression. Decompression is done by the loader, DOS32.EXE, and
can expand about 1MB/sec on a 486 33Mhz. For tightest
compression, avoid creating executable with large arrays of the
same byte. If possible, define all arrays with non-initialised
data so they are not written directly into the .EXE file.
THE DEBUGGER
This DOS extender comes with a complete debugger for the
debugging your 32bit protected mode programs. The whole debugger is
the file DEBUG.OBJ and must be to be linked in with the program that
you wish to debug. The debugger is started by executing a near call to
the external procedure named "Debug" or "Debug_Run". Calling "Debug"
will immediately start the debugger directly after this call. Calling
"Debug_Run" will only initialise the debugger and return to the
program as normal.
With this later call the debugger will only come into action when a
CPU exception occurs (such as a Page Fault, General Protection,
breakpoint) or if CTRL+BREAK key is pressed. In effect, this call is
identical as calling 'Debug' and pressing the F9 key to continue
executing.
You have probably already ran the debugger example program,
DEBUG.EXE You will find that it's similar to a conventional debugger
except it's for 32bit protected mode. The debugger will not debug when
in V86 mode or in real mode. Whenever your program calls real mode (or
V86) then the debugger will be disabled until it returns to the
program in protected mode.
The main feature of the debugger is single-stepping. Single-
stepping allows the user to execute one instruction at time and able
to see the values of each register. There are two types of stepping
available. Pressing the F7 key will step on every instruction except
for INT xx. Pressing the F8 key will step on all instructions except
for CALL, INT xx, LOOP and instructions with the REP prefix. For these
instructions that are not stepped through, the debugger will begin
normal execution of the instruction and return back to debugging mode
on the following instruction.
When stepping through, the debugger saves the value of each
register. The debugger has back stepping feature, which allows the
user to load every register to the same values as in the previous
step. The back stepping keys are ALT+F4 and can only go back up to 40
times.
You can also insert breakpoints anywhere in the code simply by
pressing F2. This will insert (or delete) an opcode 0CCh which is an
single byte to cause an interrupt 3. You will see the instruction
highlighted red. When the program is run ( F9 key ), it will stop at
the breakpoint instruction and return to the debugger. You can also
assemble your programs with an INT 3 instruction at any locations you
wish to break. For example, if you have a procedure that hangs the
system, you could assemble the program with an INT 3 somewhere inside
the procedure. The program may then simply be executed ( F9) and the
debugger will take charge soon as the INT 3 is executed.
Another feature of the debugger is toggling between the user
screen and debuggers screen by ALT+F5. When switching to the users
screens, the video mode, palette, cursor location, font memory, text
mode screen memory, and all of the _standard_ VGA registers are
restored. Non standard VGA registers are not restored so you may have
some problems in SVGA modes.
The debugger also has it's own keyboard handler. This means the
debugger is independent of the BIOS's keyboard handler. Programs can
grab IRQ 1 for their own keyboard handlers and do not need to be
redirect back to the BIOS. At any time the program is running you may
return to the debugger by pressing CTRL+BREAK keys.
When stepping through certain instructions a temporary switch to
the users screen is made. The instructions that will cause a video
switch include, LOOP, INT xx ,CALL, REP prefix, and any access to the
VGA ports. This makes sure that the VGA card is properly programmed
while debugging.
This debugger directly uses the 386's debug registers so don't
try running it under DPMI. Windows DPMI seems to handle single-
stepping and the software breakpoints, but it's not very reliable and
OS/2 hangs with blank screen, yes OS/2 can crash. I have tried using
the DPMI services for setting the debug registers but have not had
much luck. In my next version I might add support for DPMI but at the
moment I cannot be bothered with it. As it is DEBUG.ASM is already
over 140KB of assembler...( yuck )
Advanced Debugging
As well as software breakpoints ( opcode 0CCh) and single
stepping, the 386 has a set of special debug registers. There are four
breakpoint registers each of which hold a 32bit linear breakpoint
address ( registers DR0..DR3 ). Another debug register ( DR7 ) sets
the type of breakpoint for each of the four breakpoint addresses.
There is also a debug status register ( DR6 ) which contains
information for the exception 1 handler. See the Intel documentation
for a complete description of the debug registers.
The debuggers exception 1 handler will read DR6 to see what was
the caused of the exception. If the exception was caused from one of
the four breakpoint addresses then a message will be displayed on the
screen telling you which breakpoint it was and if it was an
instruction or data breakpoint. At any time the user can hold down the
CONTROL key to display the values of the four linear breakpoint
addresses and the W, R, and LEN fields from DR7.
The debugger does not set any of the debug registers however the
program that you are debugging can. Your program can load any of the
breakpoint addresses and control fields (e.g. Ri,Ei,LENi & Gi ) and
the debugger will report the breakpoint so you can then analyse the
program.
DOS32 Notes
DOS32 will run under a DPMI ( Dos Protected Mode Interface )
server if one is installed. DPMI is a bunch of services developed so
that DOS programs can run in protected mode in a multitasking
environment. Windows in enhanced mode and OS/2 supply a DPMI server
when executing a DOS program. All of the services in DOS32 will work
the same way wether it is using a DPMI server, VCPI server, XMS driver
or plain raw DOS. The VCPI ( Virtual Control Program Interface) is
what Expanded Memory Managers provide to allow dos extenders to switch
into and protected mode. Any Expanded Memory Manager, for example
EMM386.EXE, QEMM386.SYS, 386MAX, runs the CPU in V86 mode so that it
can use the 386 paging hardware to swap expanded memory pages for DOS.
If DOS32 is run when the CPU is already in V86 mode and there isn't a
DPMI or VCPI server available then it will exit with a error message
because there is no way for DOS32 to switch into protected mode.
Exceptions ( with non DPMI systems )
DOS32 will handle the exceptions interrupts 0 to 31 by displaying
a message on the screen of the type of exception, then it exits to
DOS. Your program can hook any of these interrupts but it is usually
not required.
The allocate memory service will build page tables as the memory
is allocated. This means that if you try to access memory that was not
allocated you may end up with a page fault exception. When running
under DPMI, all exceptions will be handled by the DPMI server.
Hardware Interrupt Handlers
All hardware interrupts IRQ's 0..15 can be hooked in protected
mode by using the interrupt services. When you program starts DOS32
will initially handle all the hardware interrupt vectors (including
the NMI) so they all will be redirected to the original real mode
interrupts. For example, when ever you push a key it will be calling
INT 9 in Real/V86 mode.
IMPORTANT
Never assume what will be in the segment registers in a hardware
interrupt handler. You should always preserve the segment registers
used and then load them with the desired selector. The interrupt
handler may obtain the programs data selector by referencing any
segment definition name. This was explained before above in 'Reading
the program Data Selector'.
The other important thing to remember is that when operating
under a DPMI server ALL modified interrupt vectors (INTs 0 .. 255)
should be returned to their original values before the application
terminates. When under Raw/XMS or VCPI this is not necessary to do but
should always be done for compatibility with DPMI.
Oh I almost forgot, in protected mode you cannot write to the code
segment otherwise it will cause the famous General Protection
Exception. However reading data is allowed by using the program code
selector. So a MOV CS:[0],EAX is a no no.
bugs, bugs and more bugs
A word about program bugs. Of course the more complicated a
program is the more likely it's going to have bugs. This is by far the
biggest assembler program I have ever written and so I am sure it will
have a bug or two. So I would appreciate it if you would contact me on
finding any bugs. A program like DOS32 or any DOS extender fiddles a
lot around with drivers and hardware, which means compatibility
problems across the thousands of different IBM compatible computers
available. I don't have access to very many different types of PCs so
it is hard for me to find these bugs. Of course it works flawlessly on
my computer :-)
The continuation of DOS32
I wrote this DOS extender for myself and have customised it to my
preferences. I have found no reason to have descriptor allocation
services, however some people may desperately need extra descriptors
in their programs. The VESA BIOS Extension v2.0 interface supports
protected mode applications. 32bit BUS video cards are also becoming
more popular with linear memory mapping and so I included the physical
memory mapping service, INT31h AX=800h.
If there are lots of people who are interested in this DOS
extender, it may end up becoming a big project. If there are people
who are willing to improve DOS32 or help with libraries then we may
even be able to get a team of people working on the project. I am
getting tired of the DOS32 project and I probably will not release
many more versions of DOS32. I would really like for other people who
are willing to improve DOS32 to take over and make it a bigger and
better program for the public domain. Of course, if I decide to do
this then I would have to release the entire DOS32 package source
code. It depends on how many people are interested in helping out with
DOS32. Remember DOS32 is freeware so it's here for everyone to use.
Anyone who is interested then please contact me!
Known bugs, problems and limitations
* DOS32 will not run under Novell DOS 7.0 when using it's EMS
driver. An error is reported because DOS32 can only handle interrupt
vectors of 8 and 70h for PIC #1 and PIC #2 controllers respectively.
The VCPI server in Novell EMS driver remaps the PIC interrupt vectors
some other values. However DOS32 should work fine under the Novell DOS
Raw, XMS and DPMI configurations.
* The Debugger will not correctly write to the screen while single
stepping through instructions that are accessing the video memory.
* When under Raw/XMS systems and another application has been
executed ( e.g using INT21h AH=4Bh ) which switches the 386 into V86
mode and the DOS32 application has hooked a protected mode IRQ or a
real mode call back then this protected mode IRQ handler or Call Back
procedure will not be called but rather a IRET or RETF will be
executed. This avoids DOS32 trying to do a raw switch into protected
mode while the 386 is already in control of another protected mode
program and thus causing an exception to it.
* When under raw/XMS/VCPI systems and the application has hooked
interrupt vectors 13 or 14 (IRQs 5 or 6 ) then general exceptions and
page faults will no longer be handled and may cause a "triple fault"
( CPU reset ) if one of these exceptions does occur.
* If the application has terminated and stayed resident and the
system in under XMS and any IRQ other than IRQ 1 has been hooked then
Windows cannot be loaded. This should not be too much of a problem
since most people who use Windows are fools and run a EMS driver,
thinking they are increasing available memory!.
Limitations of DLINK
Description Maximum limit
─────────────────────────────────────────────────────────────────────
Number of externals 1024 per module
Number of publics limited by memory available
Number of object modules 1024
Number of segments 100
Size of response file 6K
Size of executable 4068 Mbytes
Memory required to link approx 135Kbytes
+ total size of OBJs and LIBs
THE END
After reading all this doc, I hope you have made at least some
sense out of it. I know my english is not the greatest but you cant
complain if your getting it for free. I am also probably missing some
very important notes about DOS32.
So all in all I think ( I hope ) that this DOS extender works out
to be a very useful program for developing your software. If you are
new to 80x86 programming and what to jump straight into 32bit power
(flat memory) without getting involved with the 386's architecture
then this DOS extender is probably what your after. For people who
have only ever used real mode assembler I bet that they will be hooked
to protected mode programming once got the hang of it. The way I see
it, there is no reason why people should ever again write real mode
assembler programs when they can use DOS32.
Best of luck, and remember to support free software !
Adam Seychell.
References used in the development of DOS32;
1 Ralf Brown Interrupt listings, Release 41, 6/5/1994
2 DPMI Specification, Version 0.9, 26 July 1990
3 VCPI Specification, Version 1.0, 12 June 1989
4 eXtended Memory Specification (XMS), Version 3.0, Microsoft
Corporation, Lotus Development Corporation, Intel
Corporation,and AST Research, Inc. January 1991.
5 Microprocessors Vol 1 & 2, Intel Corporation, 1993
6 "Undocumented DOS"
7 S.P.Morse, E.J.Isaacson and D.J.Albert, "The 80386/387
Architecture", Jhon Wiley & Sons, Inc. 1987
8 Microsoft Products Support Services Application Note (Text
file) SS0288: Relocatable Object Module Format. Revision 5/92.
9 HelpPC, quick reference utility, David Jurgens, 1991
10 LZSS.C source code of, Storer and Szymanski compression
algorithm and was written in C by Haruhiko Okumura who
distributed it as public domain in the archive LZ_C.ZIP.
MASM & LINK are a trademark of Microsoft corporation.
TASM & TLINK are a trademark of Borland International.