Thunking with DOSCALL1: Difference between revisions
mNo edit summary |
mNo edit summary |
||
Line 3: | Line 3: | ||
The following entry points are probably useful for people who have to deal with thunking, i.e. translation of 0:32 pointers to 16:16 and vice versa. | The following entry points are probably useful for people who have to deal with thunking, i.e. translation of 0:32 pointers to 16:16 and vice versa. | ||
Back in the old days of OS/2 2.x/3.x, this pointer conversion was a rather simple job. Some clever programmers invented a fast mechanism to convert pointers between 16 and 32 bit, by use of the local descriptor table (LDT). | Back in the old days of OS/2 2.x/3.x, this pointer conversion was a rather simple job. Some clever programmers invented a fast mechanism to convert pointers between 16 and 32-bit, by use of the local descriptor table (LDT). | ||
The LDT was initialized to contain direct translations for the first | The LDT was initialized to contain direct translations for the first 512 MB of memory, i.e. the first 64K were mapped to LDT entry 0 (invalid, though!), the second 64k to entry 1, the third to 2 and so on. Since there are 8192 LDT entries, this sums up to 8192 * 64K = 512 MB of addressable memory. The following formulae applied: | ||
flataddr = ((((selector&0x1fff) << 3) | 0x0007) << 16) | offset | flataddr = ((((selector&0x1fff) << 3) | 0x0007) << 16) | offset | ||
and | and | ||
selector = (flataddr >> 3) >> 16 | selector = (flataddr >> 3) >> 16 | ||
offset = flataddr & 0xffff | offset = flataddr & 0xffff | ||
The formulae are written here for readability, in assembler they turn out to be pretty efficiently codeable. | The formulae are written here for readability, in assembler they turn out to be pretty efficiently codeable. | ||
Line 43: | Line 42: | ||
=== Description === | === Description === | ||
This converts a 32 bit flat address to a 16:16 far pointer to be usable by 16 bit code. This routine is callable from 16 bit code. The result is returned in eax (selector=high word, offset=low word). | This converts a 32-bit flat address to a 16:16 far pointer to be usable by 16 bit code. This routine is callable from 16-bit code. The result is returned in eax (selector=high word, offset=low word). | ||
=== Parameters === | === Parameters === | ||
Line 54: | Line 53: | ||
=== Description === | === Description === | ||
This converts a 16:16 far pointer to a 32 bit flat address to be usable by 32 bit code. This routine is callable from 16 bit code. The result is returned in eax. | This converts a 16:16 far pointer to a 32-bit flat address to be usable by 32-bit code. This routine is callable from 16-bit code. The result is returned in eax. | ||
=== Parameters === | === Parameters === | ||
Line 66: | Line 65: | ||
=== Description === | === Description === | ||
This converts a 32 bit flat address to a 16:16 far pointer to be usable by 16 bit code. This routine is callable from 32 bit code. The result is returned in eax (selector=high word, offset=low word). | This converts a 32-bit flat address to a 16:16 far pointer to be usable by 16-bit code. This routine is callable from 32-bit code. The result is returned in eax (selector=high word, offset=low word). | ||
=== Parameters === | === Parameters === | ||
Line 76: | Line 75: | ||
=== Description === | === Description === | ||
This converts a 16:16 far pointer to a 32 bit flat address to be usable by 32 bit code. This routine is callable from 32 bit code. The result is returned in eax. | This converts a 16:16 far pointer to a 32-bit flat address to be usable by 32-bit code. This routine is callable from 32-bit code. The result is returned in eax. | ||
=== Parameters === | === Parameters === |
Latest revision as of 13:13, 20 June 2023
DOSCALL1.DLL is an external extension of the OS/2 kernel that provides several translations for standard Dos* API calls.
The following entry points are probably useful for people who have to deal with thunking, i.e. translation of 0:32 pointers to 16:16 and vice versa.
Back in the old days of OS/2 2.x/3.x, this pointer conversion was a rather simple job. Some clever programmers invented a fast mechanism to convert pointers between 16 and 32-bit, by use of the local descriptor table (LDT). The LDT was initialized to contain direct translations for the first 512 MB of memory, i.e. the first 64K were mapped to LDT entry 0 (invalid, though!), the second 64k to entry 1, the third to 2 and so on. Since there are 8192 LDT entries, this sums up to 8192 * 64K = 512 MB of addressable memory. The following formulae applied:
flataddr = ((((selector&0x1fff) << 3) | 0x0007) << 16) | offset
and
selector = (flataddr >> 3) >> 16 offset = flataddr & 0xffff
The formulae are written here for readability, in assembler they turn out to be pretty efficiently codeable.
Unfortunately, this no longer works with newer kernels which allow user processes to get more than 512MB of memory; thus some sort of compatibility to old 16 bit apps has been dropped. It is now no longer guaranteed to 32 bit apps that there is a 1:1 relation between used 32 bit and 16:16 addresses through LDT, so simple arithmetic probably will no longer apply. This is particularly difficult if some 32 bit application has to transfer data to some legacy 16 bit app. This is what the following API functions are good for.
An application for these functions is described in the DDK header file ddkx86\inc\thkmacs.inc
which explains how to create handcoded thunks.
List of functions
Name | Ordinal | Type |
---|---|---|
DOSFLATTOSEL | 423 | 16bit |
DOSSELTOFLAT | 424 | 16bit |
Dos32FlatToSel | 425 | 32bit |
Dos32SelToFlat | 426 | 32bit |
DOSFLATTOSEL
Synopsis
void far* DOSFLATTOSEL(ULONG eax)
Description
This converts a 32-bit flat address to a 16:16 far pointer to be usable by 16 bit code. This routine is callable from 16-bit code. The result is returned in eax (selector=high word, offset=low word).
Parameters
eax (register)
The flat address to be converted. This argument is not passed on the stack.
DOSSELTOFLAT
Synopsis
ULONG DOSSELTOFLAT(void far* eax)
Description
This converts a 16:16 far pointer to a 32-bit flat address to be usable by 32-bit code. This routine is callable from 16-bit code. The result is returned in eax.
Parameters
eax (register)
The pointer to be converted (selector=high word, offset=lowword). This argument is not passed on the stack.
Dos32FlatToSel
Synopsis
ULONG Dos32FlatToSel(ULONG eax)
Description
This converts a 32-bit flat address to a 16:16 far pointer to be usable by 16-bit code. This routine is callable from 32-bit code. The result is returned in eax (selector=high word, offset=low word).
Parameters
- eax (register)
- The flat address to be converted. This argument is not passed on the stack.
Dos32SelToFlat
Synopsis
ULONG Dos32SelToFlat(ULONG eax)
Description
This converts a 16:16 far pointer to a 32-bit flat address to be usable by 32-bit code. This routine is callable from 32-bit code. The result is returned in eax.
Parameters
- eax (register)
- The pointer to be converted (selector=high word, offset=lowword).
This argument is not passed on the stack.