Every object is cut into pages of the header’s page size. The object page table has one
entry for each page of the module, as many as the header’s page count
(0x14), at its object page table offset (0x48, from the start
of the LX header). Each object names its first entry and how many it has; see
The object table. Entries are numbered from
1.
Page entry
An LX page entry is 8 bytes:
| Offset | Size | Field | Meaning |
|---|---|---|---|
| 0 | 4 | Page data offset | Where the page’s data is, shifted left by the header’s page offset shift: from the data pages offset, or for iterated pages from the iterated pages offset. |
| 4 | 2 | Data size | The number of bytes stored in the file. The rest of the page is zeros. |
| 6 | 2 | Flags | The page type. |
file offset = data pages offset + (page data offset << page offset shift)
bytes = data size; the page is filled up to the page size with zeros
This is the change from LE, whose 4-byte entries hold only a page number and a type, with every page but the last a whole page and all of them one after another. In LX each page says where it is and how much of it is stored, so pages can be shorter than a page and anywhere in the file.
Page types
| Value | Type | Meaning |
|---|---|---|
| 0 | Legal physical page | Stored in the file as it is. |
| 1 | Iterated data page | Stored as iterated records; see Iterated pages. |
| 2 | Invalid page | Not stored in the file. |
| 3 | Zero-filled page | Not stored; loaded as zeros. |
| 4 | Range of pages | Listed by IBM and Open Watcom, without more detail. |
| 5 | Compressed page | Compressed with EXEPACK2. Not in IBM’s 1992 description nor in Open Watcom’s header; the explorer names it from other tools, so this value is not confirmed. |
The explorer shows the stored bytes of each page, but does not expand iterated or compressed pages.
The pages
The pages start at the header’s data pages offset (0x80, a file offset).
The explorer groups the pages of each object that lie one after another in the file
into one block, named after the object, and lists the pages inside it. The executable
objects’ pages are the ones it disassembles. A page holds the object’s bytes from
j × page size on, before fixups are applied: the
fixups say what to patch.
Iterated pages
An iterated page, type 1, is stored as records that rebuild it (the explorer calls them EXEPACK pages). In IBM’s description, each record is:
| Offset | Size | Field | Meaning |
|---|---|---|---|
| 0 | 2 | Number of iterations | How many times to repeat the pattern. |
| 2 | 2 | Data length | The length of the pattern. |
| 4 | length | Data | The pattern. |
The records are expanded one after another to rebuild the page. Their offsets count
from the iterated pages offset in the header (0x4C), which is 0 or the same
as the data pages offset; the explorer uses the data pages offset when it is 0.
Per-page checksums
If the header’s per-page checksum offset (0x7C) is not 0, it points to a
table of 32-bit checksums, one for each page. The explorer shows them without checking
them.
Worked example
0000016C 00 00 00 00 00 10 00 00 01 00 00 00 00 10 00 00
0000017C 02 00 00 00 00 10 00 00 03 00 00 00 00 10 00 00
The header gives data pages at 0xE00 and a page offset shift of 12. So
page 1, offset 0, is at 0xE00; page 2, offset 1, is at
0xE00 + (1 << 12) = 0x1E00; and page 4 at 0x3E00. Each
stores all 4,096 bytes, and the last page ends at 0x4E00, the end of the
file.