home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Unsorted BBS Collection
/
thegreatunsorted.tar
/
thegreatunsorted
/
programming
/
misc_programming
/
dos32.doc
< prev
next >
Wrap
Text File
|
1993-10-04
|
11KB
|
310 lines
DOS32 V0.1
A 386 32 bit dos extender for Assembly Programmers.
Written By Adam Seychell. (5 / SEP / 1993)
email s921880@minyos.xx.rmit.oz.au
Copying.
Feel free to copy and distribute this DOS extender.
Use it in your programs any way you wish. I am
distributing this to get people more familiar with
protected mode programming.
However if you do make use of it in your program I would
appreciate if you credit me for the dos extender. Also if
you use it to write anything great could you send me a copy.
of it. I have spent a lot of hours writting this DOS extender.
********* FEATURES **********
* Supports DPMI ( windows and OS/2 compatibility !!! )
* Supports XMS
* Supports No memory mangers ( most powerful )
* Data and code segment descriptors avalible for
1. Your ASM segment.
2. Flat memory.
3. Base memory.
4. An allocated extended memory block
( size is defined by you).
* Functions to set/get protected mode interrupt
descriptor vectors.
* Calling real mode interrupts is nearly as easy as
calling in real mode itself. Switches to V86 mode when
called.
* Supports the SYSTEM BIOS COPY EXTENDED MEMORY BLOCK
function INT 15h, AH = 87h for real mode. So a real
mode TSR that calls this BIOS function (eg. HIMEM.SYS )
will be emulated the dos extender. This allows TSRs like
disk caches to be running.
******** KNOWN PROGRAM BUGS ***************
There is a problem with the BIOS int 15h ah = 87 emulation.
Only HIMEM.SYS calls it to transfer a XMS block while MSDOS
is loaded in the Upper Memeory Block. It seems to be called
with the location of the GDT ( for int 15 ah=87 ) in the ROM
area. This gives an invalid GDT.
When DOS is loaded into convention memory everything work fine because
HIMEM.SYS supplies a valid GDT to this call.
Introduction.
DOS32.ASM is a 386 protected mode initialise
program. The purpose of it is to make protected mode
programming very easy. When I was writing DOS32.ASM my aim was
to use full 32bit power of the 386 while making it as easy as
possible to program.
The DOS32.ASM is meant to be assembled as an object
file and then linked to you assembler program. You ASM file
must follow the following rules. Again, I tried to make this
simple as possible.
* Requires a small include file to setup macros,
structures ect.
* You must have the code segment named CODE32 and a data
segment named DATA32.
* Never change the stack segment register, i.e. SS.
* Pass V86 mode segment registers on stack when calling
V86 mode. ( see below for details)
* The first 32 bytes of the stack are reserved.
i.e locations ss:[0] up to ss:[1Fh]
* Must have a starting point called "START32:" in the
code segment.
* Requires you to load valid selectors in ES,GS,FS at
startup
* Must only terminate the program with INT 21h, AH = 4Ch.
**** DETAILS ON WHAT DOS32 DOES. *****
DOS32.ASM basicly contains code to set up segment descriptors
in the LDT or GDT, enter/exit protected mode, allocated/free a
extended memory block and call real mode interrupts. These
parts of the DOS32.ASM will never have to be called directly
form your program.
Note. If operating under DPMI then all DPMI services will be
available.
When not operating under DPMI there are two services in the
dos extender to set and get the protected mode interrupt
vectors. These will work exactly the same as DPMI services.
SET interrupt
ax = 204h
bl = interrupt number
edx = offset
cx = selector
int 31h
returns: carry set on error
GET interrupt
ax = 205h
bl = interrupt number
int 31h
returns: edx = offset
cx = selector
Also the Programible Interrupt Controllers ( 8259) base vector
values can be obtained from the DPMI Get Version function, int 31h
ax = 400h. If not running under DPMI then only the PIC bases
are returned.
DH = master PIC ( pic 2 )
DL = slave PIC ( pic 1 )
AVAILABLE DESCRIPTORS .
There are nine available descriptors for you program
that DOS32.ASM initially sets up. The selector values for each
descriptor is stored in the data segment under the labels:
PSP_sel :Data descriptor for the Program Segment Prefix
Base = the real mode PSP segment.
Limit = 100h
Data_sel :Data descriptor for the your data segment "DATA32"
Base = the real mode data segment.
Limit = 1MB
Code32_sel :32 bit code descriptor for the your code segment "CODE32"
Base = the real mode code segment.
Limit = 1MB
TheStack_sel :Data descriptor for the stack
Base = the real mode stack segment.
Limit = See DOS32.ASM
XMS_sel :Data descriptor for the allocated extended memory
Base = the base address of the block
Limit = Size of allocated block ( see below)
BASE_sel :Data descriptor for the free base memory
Base = the unused base memory straight after
MSDOS loads in you program. (see below)
Limit = 1Mb
VIDEO_sel :Data descriptor for the video area.
Base = A0000h
Limit = 20000h
FLAT_DATA_sel :Data descriptor for a flat memory model
Base = 0
Limit = FFFFFFFFh
FLAT_CODE32_sel :32 bit code descriptor for a flat memory model
Base = 0
Limit = FFFFFFFFh
The first instruction of you program will be executed is
at offset "start32:" in your code segment.
Your program is initially started with DS pointed to your
data segment ( DATA32 ) and ESP and SS setup for the stack.
The stack size is given by the equate in DOS32.ASM "Normal_stack".
I've set the value to 200h bytes, but can be changed if required.
NOTE: Your program must load valid selectors into ES,FS,GS if
it's going to use any of them.
example
;----------------------------------------
start32: ; starting point
mov gs,[flat_sel]
mov es,[flat_sel]
mov fs,[xms_sel]
...
... You program
...
...
mov ah,4ch ; terminate
int 21h
;----------------------------------------
One more feature with DOS32.ASM is that in the data segment
there are four labels in the data segment with information
about memory.
1) "Base_Segment" will contain a real mode segment value
of the start of free base memory. i.e The value stored in
this label * 16 = the base address of the BASE_sel descriptor.
2) "PSP_segment". The real mode segment vlaue of the
program segment prefix.
3) "XMS_base". Contains the linear base address of the
allocated extended memory block.
4) "XMS_usage". This location contains the size of the
allocated extended memory block required by your program.
DOS32.ASM will read the value of this Label and attempt to
allocate that amount of memory. If there isn't a enough free
memory then DOS32.ASM will allocate as mush as it can and
return what was actually allocated back into this Label.
Notes
o The XMS_sel descriptor Limit is set to this value.
o The Memory allocated will never be greater than
lockable memory.
o If the XMS driver nor DPMI is available then the
entire extended memory will be allocated by the xms
descriptor. base = 0100000h , limit = available ram.
o If XMS_usage is zero then no memory will be
allocated and the XMS_sel will point to a invalid
descriptor.
Calling a Real mode interrupt:
This is one of the most useful features of DOS32.ASM. The
way the interrupt is called is through the macro "DOSINT"
followed by the interrupt number. This macro actually consists
of two instructions, mov & int 20h ( see DOS32.INC).
When the real mode interrupt is called, all the
32bit general registers and the 16bit flags ( except for ESP )
are loaded with the same values they were in protected mode.
Because in protected mode the segment registers cant be loaded
with any value (except for valid selectors) a different method
is used to pass the segment register values.
The segment registers values MUST be passed from
protected mode to the called real mode interrupt through the
stack segment. This is located in the stack at the first 4
dwords and has the following format.
ss:[00h] holds the GS register
ss:[04h] holds the FS register
ss:[08h] holds the DS register
ss:[0Ch] holds the ES register
This is the easiest and most versatile way I could
think how to do it. Using the stack instead of say a data
segment don't require DS,ES,GS or FS segment registers to be
loaded with a specific selector. This is because SS will
always contain the stack selector. I have included a data
structure to make it easier to load these locations ( see the
file DOS32.INC ).
eg . to print a string using dos func 9 int 21h
;---------------------------------------------------------
mov SS:Real_DS ,seg test_message ; pass DS register
mov ah,9
mov dx,offset test_message
dosint 21h
mov ah,4ch ; Terminate program
int 21h
db test_mesg ' String message using dos func ah = 9 ',10,13,36
;---------------------------------------------------------
Just like calling real mode int, all the general registers,
flags and segment registers(on the stack segment) will be
returned with the values after the real mode interrupt call.
The only thing to left to say about the called real
mode interrupt is that the stack is set up by DOS32.ASM and
cant be altered throng your program. The real mode stack space
is defined by an equate in DOS32.ASM called "V86_stack_size". It
is initially set to 200h and shouldn't need to be changed. I
thought this should be a safe value.
**** I don't ever want to here of people complaining
about the 640K limit for there own assembly programs !