DOS32 Version 3.2 Applications Programming Interface (API) 27 November 1995 Copyright (C) 1994 Adam Seychell, All Rights Reserved. This document contains detailed information of the DOS32 API with each function obeying the following rules. * All services are invoked from software interrupts 31h or 21h. * Never call a function in a protected mode interrupt handler unless otherwise said it is safe to do so. * All services will preserve registers which are not returned with any value. The Interrupt 31h services. The following list of services are called from INT 31h with AX containing the function number. GET DOS32 VERSION AND SELECTOR VALUES V3.00+ IN: AX = EE00h OUT: AL = minor version ( BCD ) currently 01 AH = major version ( BCD ) " 03 DL = system type 1 = raw DOS 2 = XMS 4 = VCPI 8 = DPMI BX = Selector of 4GB data segment with zero base address. Notes: o This function may be called in a protected mode interrupt handler. GET DOS32 ADDRESS INFORMATION V3.01+ IN: AX = EE02h OUT: EBX = 32bit linear address of the program segment EDX = Total size in bytes of the programs .EXE file after linking. ESI = Offset address of PSP ( Program Segment Prefix ) EDI = Offset address of Program Environment ECX = Offset address of the programs .EXE file name and path (in ASCIZ format, i.e. terminates with a zero) AX = Real mode segment value of the 8Kb buffer that is used by the file read/write services. Notes: o All offset addresses returned are relative to the main program segment. o The .EXE file size is generally used for loading extra data appended to the original application's .EXE file. The application may simply seek to this position to access the appended data. o The .EXE file name pointed by ECX is actually the file name contained in the last string of the Environment segment pointed to by EDI. o The PSP address points to the original PSP set up by DOS. Thus pointers stored in here still contain real mode (segment:offset) values. Also this PSP address may not be the same address returned by DOSs Int 21h AH=62h (Get PSP) since DOS32 may of been loaded by a parent stub program. o Since the segment address returned in AX points to the 8Kb buffer used by the virtualized 32bit file read/write service (INT 21h AH=3Fh/40h) then the contents of this buffer will be distroyed apon call to these services. However, the application may make temporary use of the buffer rather than allocating a separate DOS block for transferring data between real mode and protected mode. The near pointer of the buffer will be equal to (16*AX - EBX) o This function may be called in a protected mode interrupt handler. TERMINATE AND STAY RESIDENT v3.00+ This service will terminate the application to DOS but leaving it resident in memory. IN: AX = EE30h OUT: Never returns Notes: o All memory allocated from functions AX=0EE42h (memory block) and AX=EE41h ( DMA buffer ) will not be freed and stay allocated. o This service may come in handy. Now.... what could you write with a multi megabyte TSR ?? DOS32 LOADABLE LIBRARIES (DLL files) The following functions are used for handling loadable library files supported by DOS32. There are three main steps necessary to use a loadable library. These may be ordered as follows; 1) use function EE10h to setup the library file. 2) allocate memory block of size required by the library. 3) use function EE11h to load library into memory. 4) the address of the library public variable can then be used to access its code and/or data. SET UP A LOADABLE LIBRARY FILE V3.2+ This function is used to set up a DOS32 dynamic loadable library for the application to use. Expects: AX = EE10h EDX = Pointer to a string of the library path\filename. (terminates with zero) EBX = Number of bytes to seek from beginning of file. Returns: If function was successful: Carry flag is clear. EAX = Size of memory block required to store library. EBX = size of library file in bytes. If function was not successful: Carry flag is set. AL = error code. 01 = Error opening or reading file. 02 = Bad DOS32 library file. NOTES: o The value returned in EAX is the size of the memory block that must be allocated in order to load the library into memory with function EE11h. o The seeking position, expected in EBX, tells DOS32 that the Loadable Library starts EBX bytes from the beginning of the file. o The value returned in EBX is equal to the total size of the library file when it was originally created by DLINK. Data appended to the library file has no effect on this value. Together with the seeking position, expected in EBX, it allows Libraries files to be stored in middle of a larger file, for example, the applications EXE file. LOAD LIBRARY V3.2+ This function is used to load the library file into memory. Once loaded the application can then use the libraries code/data. Expects: AX = EE11h EDX = Near pointer of memory block to store library. Returns: If function was successful: Carry flag is clear. EDX = Near pointer to the dynamic global public variable. If function was not successful: Carry flag is set. Notes: o Never call this function without first successfully setting up the library with function EE10h. o The size of the memory block used to store the library must be equal to size returned in EAX from function EE10h. o Since the libraries code and data will be stored at the address specified in EDX, it should always be aligned on a 4 byte boundary. o The pointer returned in EDX points to the public symbol defined in the Loadable Library file. Typically the library will define this public variable as array of pointers to each function in the library. The programmer may use this common address between the application and library for any purpose. GET A REAL MODE CALL BACK ADDRESS WITH IRET OR RETF STACK FRAME V3.00+ This service is used so that real mode software can call the protected mode application. This function returns a real mode address which when called (in real mode) will invoke a protected mode procedure. The real mode address may either be called with a FAR CALL or from an INT n. Expects: AX = EE20h ( for an RETF stack frame ) AX = EE21h ( for an IRET stack frame ) ESI -> Offset address of the protected mode procedure to be invoked when the real mode address is called. The procedure must exit with a FAR return. Returns: If function was successful: Carry flag is clear. CX:DX = The real mode far pointer ( SEG:OFFSET ) to call the protected mode procedure. If function was not successful: Carry flag is set. Notes: o This function will fail if it's called more than 30 times. o The protected mode procedure must exit with a FAR return instruction. o The procedure is called with undefined selectors in all segment registers ( ES,DS,FS,GS & SS ) and is not required to preserve any segment registers it modifies. o EAX, EBX, ECX, EDX, ESI, EDI, EBP registers and flags will be preserved across the mode switches. o This function can be used to hook a Real Mode interrupt by setting a real mode interrupt vector to point to the real mode address (CX:DX) returned by this function. See examples on how this may be done. UNDO PREVIOUS MEMORY ALLOCATION v3.00+ This function will free the previously allocated memory block ( function AX =EE41h ) or DMA buffer ( function AX=EE42h ) If this function is called multiple times then memory will be deallocated in reverse order to when allocated. For example, if a memory block was allocated followed by a DMA buffer then at first time this function is called the DMA buffer would be freed, a second call to this function will free the memory block, a third call will return an error ( Carry set ) because at this point no memory is being allocated. IN: AX = EE40h OUT: If function successful carry flag is cleared If unsuccessful the carry flag is set Notes: o This function will fail if there is no memory allocated. o All memory will automatically be freed when then application terminates. 16KB BLOCK ALLOCATION FOR DMA CONTROLLER V3.00+ This function allocates a DMA buffer allowing the application to do DMA transfers of up to 16KB at a time. Expects: AX = EE41h Returns: If function was successful: Carry flag is clear. EBX = Physical address of a contiguous 16KB memory block that dose not cross a 64KB boundary and has a physical address in the lower 16MB. EDX = Near pointer to the base address of the block relative to the main program segment. If function was not successful: Carry flag is set. NOTES: o The 16Kb block will not cross a physical 64KB boundary and will have a base address aligned on a 4 byte boundary. This is just what DMA needs!. o If the carry flag is set then there was not enough memory to allocate the DMA block otherwise the carry flag is cleared. o If the application needs to do use more than one DMA channel at the same time ( e.g reading floppy disk at the same time as sending music to a sound card ) then a buffer could be allocated for each channel used. o If all available memory was allocated by the Allocate Memory service ( AX=0EE42h ) then this function will fail. Your application should allocate it's DMA buffers before is tries to allocate large blocks with the AX=0EE42h function. o If you need to send large amounts of memory via DMA to a device then it will have to be done in 16KB blocks. I know this sounds very inefficient but I done tests and found that I could not even measure the speed increase between 1Kb blocks to 128Kb blocks. Only a noticeable slow down occurred when transferring with blocks of 100 bytes or less. In fact the time it takes to program the DMA controller and move a 16KB block to the buffer ( using REP MOVSD ) is under %1 of the DMA transfer time. In other words, it will be less than %1 slower using a buffer as opposed to transferring DMA directly to/from the data area. ALLOCATE A MEMORY BLOCK V3.00+ The entire application code,data and stack is initially contained in one large memory block. This service here is used for allocating extra memory blocks for the application. IN: AX = EE42h EDX = Size of the memory block requested to allocate in bytes. OUT: EAX = The actual allocated size of the memory block in bytes EDX = Near pointer to the base address of the block relative to the main program segment. If the returned size was less than the requested size then the Carry flag is set otherwise the carry flag is cleared. Notes: o The value expected in EDX will be rounded off to the next 4KB boundary. Example, allocating 51001h bytes will actually allocate 52000h bytes. o Never call this function in a interrupt handler or after using the terminated and stay resident function ( AX=EE30h ). o If EAX is returned with zero then no memory was allocated and contents of EDX are undefined. o The function will fail if the requested size is zero. o No more than 64 allocations can be made. If the application requires a faster more versatile memory management then please use Peter Anderson's memory sub-functions from PAL library. See example files on how to use. This function here is should used a minimum number of times. o When not running under a DPMI server ( i.e Raw,XMS or VCPI ) then extended memory is allocated before conventional memory is. For example, if there is no more extended memory free then conventional memory will be allocated. In either case DOS32 sets up the 386 page tables such that the allocated memory is addressed in a straight linear block when it may actually be physically scattered throughout RAM. The Interrupt descriptor table services These services allow the application to get and set vectors of the protected mode interrupt descriptor table. The hardware interrupt vectors will always be set the default values. i.e IRQs 0..7 map onto CPU interrupts 8..15 and IRQs 8..15 map onto CPU interrupts 70h..77h. All protected mode interrupt vectors will initially reflect to the same interrupt in real mode. In other words a switched to and from real mode is automatically made when a protected mode interrupt is called. The registers EAX,ECX,EDX,EBX,EBP,ESI,EDI and flags will be preserved across the mode switch. The exception to this rule are protected mode interrupts 0,1,3,4,5,6 and 7. These are exceptions and will terminate the program reporting with an error on the screen. Hardware interrupt handlers will be called with undefined selectors in all data segment registers. The interrupt handler must preserve all modified general registers and segment registers before it returns from the interrupt. The application is responsible for returning the original interrupt vectors before the application terminates. It is only necessary do to this when running under a DPMI server. However, for reliability, ALL modified interrupt vectors should be restored to their original value. GET PROTECTED MODE INTERRUPT VECTOR V3.00+ IN: AX = 0204h BL = interrupt OUT: EDX = The 32 bit offset of the vector CX = Selector of vector SET PROTECTED MODE INTERRUPT VECTOR V3.00 IN: AX = 0205h BL = interrupt EDX = The 32 bit offset of the vector CX = Selector of vector ( must be a code selector ) OUT: nothing REAL MODE CALL SERVICES The following three services are used for calling real mode programs (e.g a DOS call or a device driver). Each of these services operate identically to the DPMI specification (AX=300h/301h/302h). Each function expects a pointer to a real mode call structure whish is used to passing all registers to and from the real mode switch. The format of the structure is defined as: Offset Register 00h EDI 04h ESI 08h EBP 0Ch Reserved by system 10h EBX 14h EDX 18h ECX 1Ch EAX 20h Flags 22h ES 24h DS 26h FS 28h GS 2Ah IP 2Ch CS 2Eh SP 30h SS Simulate a Real Mode interrupt V3.00+ IN: AX = 0300h BL = Interrupt number BH = Flags Bit 0 = 1 resets the interrupt controller and A20 line. Other flags reserved and must be 0 CX = Number of words to copy from protected mode to real mode stack ES:EDI = Selector:Offset of real mode call structure OUT: If function was successful: Carry flag is clear. ES:(E)DI = Selector:Offset of modified real mode call structure If function was not successful: Carry flag is set. Call Real Mode Procedure With Far Return Stack Frame V3.00+ IN: AX = 0301h BH = Flags Bit 0 = 1 resets the interrupt controller and A20 line. Other flags reserved and must be 0 CX = Number of words to copy from protected mode to real mode stack ES:EDI = Selector:Offset of real mode call structure OUT: If function was successful: Carry flag is clear. ES:EDI = Selector:Offset of modified real mode call structure If function was not successful: Carry flag is set. Call Real Mode Procedure With IRET Stack Frame V3.00+ IN: AX = 0302h BH = Flags Bit 0 = 1 resets the interrupt controller and A20 line. Other flags reserved and must be 0 CX = Number of words to copy from protected mode to real mode stack ES:EDI = Selector:Offset of real mode call structure OUT: If function was successful: Carry flag is clear. ES:EDI = Selector:Offset of modified real mode call structure If function was not successful: Carry flag is set. PHYSICAL MEMORY MAPPING V3.01+ The follwing function is used to access an area of physical memory above the first 1Mb. Some devices require a region in the physical address space to transfer data. An example would be a video card in linear address mapping mode. IN: AX = 0800h BX:CX = Physical address of memory SI:DI = Size of region to map in bytes OUT: If function was successful: Carry flag is clear. BX:CX = Linear address that can be used to access the physical memory. Notes: o The physical memory address should not in the lowwer megabyte Only memory above 1Mb is allowed to be mapped. o No more than 32Mb can be mapped with this function. o The address returned in BX:CX is a linear address. To translate into an offset address subtract the program base address ( see INT31h AX=EE02 ) with the contents of BX:CX. The 32 bit DOS type services The following services are like a protected mode version of DOS's services. They are called the same way as in real mode where AH=function and invoked with INT 21h. The main differences is the use of protected mode 48bit far pointers (selector:offset) and 32bit registers rather than only 16bit registers and real mode far pointers (segment:offset). For a more detailed description of how the services work please refer to DOS programming documentation. The description below is only to show the use of 32 bit registers. NOTE: If an INT 21h function is called and is not described here then the interrupt is done in real mode with all the registers passed to from the call. This is also the case for any other protected mode interrupt, not just INT 21h!. ------------------------------------------------------------------ WRITE STRING TO STANDARD OUTPUT V3.0+ AH = 09h DS:EDX -> '$'-terminated string ------------------------------------------------------------------ CREATE SUBDIRECTORY V3.0+ AH = 39h DS:EDX -> Selector:Offset of ASCIZ pathname Return: CF clear if successful AX destroyed CF set on error AX = error code (03h,05h) ------------------------------------------------------------------ REMOVE SUBDIRECTORY V3.0+ AH = 3Ah DS:EDX -> Selector:Offset ASCIZ pathname of directory to be removed Return: CF clear if successful AX destroyed CF set on error AX = error code (03h,05h,06h,10h) ------------------------------------------------------------------ CHANGE SUBDIRECTORY V3.0+ AH = 3Bh DS:EDX -> ASCIZ pathname to become current directory (max 64 bytes) Return: CF clear if successful AX destroyed CF set on error AX = error code (03h) ------------------------------------------------------------------ CREATE OR TRUNCATE FILE V3.0+ AH = 3Ch CX = file attributes DS:EDX -> Selector:Offset ASCIZ filename Return: CF clear if successful AX = file handle CF set on error AX = error code (03h,04h,05h) ------------------------------------------------------------------ OPEN EXISTING FILE V3.0+ AH = 3Dh AL = access and sharing modes DS:EDX -> Selector:Offset ASCIZ filename CL = attribute mask of files to look for (server call only) Return: CF clear if successful AX = file handle CF set on error AX = error code (01h,02h,03h,04h,05h,0Ch,56h) ------------------------------------------------------------------ READ FROM FILE OR DEVICE V3.0+ AH = 3Fh BX = file handle ECX = number of bytes to read ( may be zero ) DS:EDX -> Selector:Offset buffer for data Return: CF clear if successful EAX = number of bytes actually read (0 if at EOF before call) CF set on error AX = error code (05h,06h) ------------------------------------------------------------------ WRITE TO FILE OR DEVICE V3.0+ AH = 40h BX = file handle ECX = number of bytes to write DS:EDX -> Selector:Offset data to write Return: CF clear if successful EAX = number of bytes actually written CF set on error AX = error code (05h,06h) ------------------------------------------------------------------ DELETE FILE V3.0+ AH = 41h DS:EDX -> Selector:Offset ASCIZ filename (no wildcards ) Return: CF clear if successful CF set on error AX = error code (02h,03h,05h) ------------------------------------------------------------------ SET CURRENT FILE POSITION V3.0+ AH = 42h AL = origin of move 00h start of file 01h current file position 02h end of file BX = file handle EDX = offset from origin of new file position Return: CF clear if successful EAX = new file position in bytes from start of file CF set on error AX = error code (01h,06h) Notes: The normal real mode DOS function uses CX:DX as the position of the file to seek and returns DX:AX with the new value of the position. This protected mode version uses EDX in place of CX:DX and uses EAX in place of DX:AX. ------------------------------------------------------------------ GET FILE ATTRIBUTES V3.0+ AX = 4300h DS:EDX -> Selector:Offset ASCIZ filename Return: CF clear if successful CX = file attributes AX = CX (DR-DOS 5.0) CF set on error AX = error code (01h,02h,03h,05h) ----------------------------------------------------------------- SET FILE ATTRIBUTES V3.0+ AX = 4301h CX = new file attributes DS:EDX -> Selector:Offset ASCIZ filename Return: CF clear if successful AX destroyed CF set on error AX = error code (01h,02h,03h,05h) ------------------------------------------------------------------ GET CURRENT DIRECTORY V3.0+ AH = 47h DL = drive number (00h = default, 01h = A:, etc) DS:ESI -> Selector:Offset 64-byte buffer for ASCIZ pathname Return: CF clear if successful AX = 0100h (undocumented) CF set on error AX = error code (0Fh) ------------------------------------------------------------------ LOAD AND/OR EXECUTE PROGRAM V3.0+ AH = 4Bh AL = type of load 00h load and execute 01h load but do not execute DS:EDX -> ASCIZ program name (must include extension) DS:EDI -> Program environment to copy for child process (copy caller's environment if EDI = zero ) DS:ESI -> pointer to command tail to be copied into child's PSP Return: CF clear if successful CF set on error AX = error code (01h,02h,05h,08h,0Ah,0Bh) Notes: Unlike DOS's 4Bh function this does not require a parameter block to be set up. The environment and command tail are pointed to by DS:EDI and DS:ESI respectively. See the examples distributed with DOS32 on how this function may be used. It seems that MS-DOS will redirect the current DTA address after this function is called. When this service is called the current DTA address will be reset to the default area of 80h bytes ahead the PSP address. o The command line string is expected in the Pascal string format. The first byte represents the number of characters in the string followed by the actual string . ------------------------------------------------------------------ TERMINATE WITH RETURN CODE V3.0+ AH = 4Ch AL = return code Return: never returns Notes: o DOS32 applications MUST ALWAYS terminate with this call. o All memory allocated ( including DMA buffers and DOS blocks ) will automatically be freed when the application terminates with this call. ------------------------------------------------------------------ FIND FIRST MATCHING FILE V3.0+ AH = 4Eh CX = file attribute mask DS:EDX -> ASCIZ file specification (may include path and wildcards) Returns: CF clear if successful The DTA ( Disk Transfer Area ) is filled with file information. CF set on error AX = Error code (02h, 03h, or 12h) Notes: The DTA is set to the default area which is at offset 80h in the Program Segment Prefix (PSP). See function INT 31h AX=EE02h for obtaining the PSP address. ------------------------------------------------------------------ RENAME FILE V3.0+ AH = 56h DS:EDX -> ASCIZ filename of existing file (no wildcards ) ES:EDI -> ASCIZ new filename (no wildcards) Return: CF clear if successful CF set on error AX = error code (02h,03h,05h,11h) ------------------------------------------------------------------ CREATE TEMPORARY FILE V3.0+ AH = 5Ah CX = file attribute DS:EDX -> ASCIZ path ending with a '\' + 13 zero bytes to receive the generated filename. Return: CF clear if successful AX = file handle opened for read/write in compatibility mode DS:EDX -> pathname extended with generated name for temporary file. CF set on error AX = error code (03h,04h,05h) ------------------------------------------------------------------ CREATE NEW FILE V3.00+ AH = 5Bh CX = file attribute DS:EDX -> ASCIZ filename Return: CF clear if successful AX = file handle opened for read/write in compatibility mode CF set on error AX = error code (03h,04h,05h,50h) < END OF DOS32 API >