home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS - Coast to Coast
/
simteldosarchivecoasttocoast2.iso
/
asmutil
/
dos32v12.zip
/
DOS32.DOC
< prev
next >
Wrap
Text File
|
1993-10-22
|
11KB
|
312 lines
DOS32 V1.2
Copyright Adam Seychell Oct\1993
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 program.
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 use this software I require that you
credit me for its use. Also if you write anything great
I would appreciate if you could 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 segment descriptors for
2. A Flat memory model.
3. Conventional memoryn block.
4. An allocated extended memory block
( size is defined by you).
* All selector values are stored in the code segment.
* 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 and ram drives to be running.
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. I tried to make this
simple as possible.
* The segment of your 32 bit program must be named CODE32
* Pass V86 mode segment registers in the program segment.
( see below for details)
* Must have a starting point called "START32:" in your
program segment.
* Requires you to load valid selectors in ES,GS,FS,SS,DS and
set the stack pointer ( ESP ).
* Must terminate the program with INT 21h, AH = 4Ch.
* Requires a small include file to setup macros,
structures ect.
**** 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.
Your programs code and data segment descriptors have the same
base addresses. This base address in equal to the address of
the CODE32 segment. It is easier to program with only a single
code and data segment area. The stack can be anywhere you
want it to be.
DOS32 SERVICES
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 the real 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 eight 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
ENVIRONMENT_sel :Data descriptor for the Program Environment
Base = 16 multiplied by the word at offset 2Ch of the PSP.
Limit = 100h
Data_sel :Data descriptor for your program segment "CODE32"
Base = the real mode program segment.
Limit = 1MB ( B=1 . i.e uses 32bit stack mode)
Code32_sel :32 bit code descriptor for your program segment "CODE32"
Base = the real mode program segment.
Limit = 1MB
XMS_sel :Data descriptor for the allocated extended memory block
Base = the base address of the block
Limit = Size of the 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 program segment with interrupts
DISABLED.
Your program is initially started with undefined selectors in
all the data segemnt registers ( ES,DS,FS,GS,SS).
Thus your program must load valid selectors into ES,FS,GS,DS,SS if
it's going to use any of them.
The stack pointer is also need to be loaded to a stack area.
Initially there is a *SMALL* stack but I recomend to set your own.
Example of initalize with the stack in your program segment.
;----------------------------------------
CODE32 SEGMENT USE32
start32: ; starting point
mov ds,cs:[ Data_Sel] ; Load all data Segment registers
mov gs,cs:[ Flat_Sel]
mov es,cs:[ Flat_Sel]
mov fs,cs:[ XMS_Sel]
mov ss,cs:[ Data_Sel]
mov esp,OFFSET your_stack
sti ; Can now enable interrupts safely
...
... You program
...
...
mov ah,4ch ; terminate
int 21h
db 1000h (?) ; set up some stack area
your_stack:
CODE32 ENDS
;----------------------------------------
One more feature with DOS32.ASM is that in the program segment
there are four labels with usful 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 number of bytes
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 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 when in a virtual disk environment.
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 three instructions ( 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 several
labels in your program segment. See the file DOS32.INC for the
declearation of these labes ( or locations ).
They are named:
Real_DS ; holds the DS register when in V86 mode.
Real_ES ; holds the ES register when in V86 mode.
Real_FS ; and so on
Real_GS
Real_SS ; These are already loaded by DSO32 with
Real_SP ; V86 stack area. See below.
This is the easiest and most versatile way I could
think how to do it.
eg . to print a string using dos func 9 int 21h
;---------------------------------------------------------
mov [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'
db ' in protected mode.',10,13,36
;---------------------------------------------------------
Just like using a real mode INT, all the general registers,
flags and segment registers(stored in you program segment) will be
returned with the values after the real mode interrupt call.
V86 MODE STACK AREA
The only thing to left to say about the called real
mode interrupt is that the stack is initaly set up by DOS32.ASM.
Although you can set the V86 mode stack by simply loading the lables
[Real_SP] and [Real_SS], DOS32 already sets aside some a stack area .
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 !