An NE module that calls functions in other modules, such as KERNEL, USER and GDI, names those modules in two tables. The module reference table lists them, and the imported names table holds their names and the names of any functions imported by name. The imports themselves are relocation records in the segments that call them.
The module reference table
The table is at ne_modtab
from the start of the NE header: ne_cmod
words, each the offset of a module’s name in the imported names table. Relocation
records refer to a module by its index here, counting from 1. The same module can
appear more than once. The explorer lists the modules in its Imported modules table, in
this order.
The imported names table
The table is at ne_imptab
from the start of the NE header. It has no size of its own: it runs up to the entry
table, at ne_enttab. It holds length-prefixed strings, each a length byte
and that many characters, with no zero at the end and no end mark. The first byte is
usually a string of length 0, so that offset 0 is never a real name.
Module names and the names of functions imported by name are both kept here. A
relocation record that imports by name gives the offset of the function’s name from the
start of this table; one that imports by ordinal gives just the number. The explorer
shows a named import as MODULE!Name and one by ordinal as
MODULE.91.
Worked example
TEST1.EXE imports from 6 modules. Its module reference table is at 0x16D
and its imported names table at 0x179:
0000016D 01 00 08 00 0C 00 11 00 18 00 1D 00 ............
00000179 00 06 4B 45 52 4E 45 4C 03 47 44 49 04 55 53 45 ..KERNEL.GDI.USE
00000189 52 06 4B 45 52 4E 45 4C 04 55 53 45 52 08 4B 45 R.KERNEL.USER.KE
00000199 59 42 4F 41 52 44 YBOARD
| Index | Offset | Module |
|---|---|---|
| 1 | 0x0001 | KERNEL |
| 2 | 0x0008 | GDI |
| 3 | 0x000C | USER |
| 4 | 0x0011 | KERNEL |
| 5 | 0x0018 | USER |
| 6 | 0x001D | KEYBOARD |
KERNEL and USER each appear twice, under different indexes. The table ends at
0x19E, and the entry table starts at 0x19F.