Purpose of the M-bit and FRAME DATUM Fields

ID Number: Q66579

3.x 4.x 5.x | 3.x 4.x 5.x

MS-DOS | OS/2

Question:

I have read the discussion of the Microsoft OBJ layout in the "MS-DOS

Encyclopedia" but I still have the following questions:

1. What is the M-bit field in the FIXUP record used for?

2. It would seem that the fields TARGET DATUM and TARGET DISPLACEMENT

should be all that is required to fix up any references in a LEDATA

or LIDATA record. What is the FRAME DATUM field used for?

Response:

1. The exact use of the M bit is exactly as stated in the "MS-DOS

Encyclopedia." That is, should the linker calculate the address to

place in the FIXUP record from the start of the segment in question

(segment-relative), or from the current location in the code/data

(self-relative)? The following is an example:

FOO Segment

--> +-----------------+ <-- Start of segment

| | |

| | |

| | |

| | |

| --> +-----------------+ <-- Reference to symbol

| | | |

| | |

(A) | | |

/ \

| (B) \ /

| / \

| | \ /

| | | |

| | | |

--> --> +-----------------+ <-- Symbol

/ \

\ /

/ \

\ /

+-----------------+ <-- End of segment

In this example, (A) is the segment-relative address and (B) is the

self-relative address. The self-relative calculation is used when you

want to jump forward a certain number of bytes in the code (for

instance, a short jump). The calculation is fairly straightforward.

Calculate the segment-relative address for the symbol. Subtract the

segment-relative address of the reference, and you have the

self-relative address for the symbol from the reference.

2. The FRAME DATUM field is used in almost exactly the same manner. To

understand why it is required, see the following example:

The Microsoft C compiler generates a DGROUP group that holds _NULL,

_DATA, _CONST, etc. The FIXUP records it generates are similar to

the following:

frame DGROUP target _CONST

and

frame DGROUP target _DATA

and

...

For the average DOS program, this is fine. We could, if we wanted to,

eliminate the FRAME DATUM field and change target to DGROUP, right?

Wrong. Examine ROMable code; they use the same OBJ. In that case, the

linker must know if a reference to _CONST is a far reference (based on

DGROUP) or a near reference (based on CONST). If we only told it to

use DGROUP, it would have no idea how to resolve the references to

_CONST after it moved _CONST to another segment (for example, ROM

based). If we left in the target _CONST and removed the frame DGROUP,

we would have the wrong address for DOS, right? Hence, FRAME DATUM

*is* important.

The way the FRAME DATUM field affects the FIXUP value is probably

obvious, given the example above for the M-bit. Just calculate the

offset based on the TARGET segment and add in the offset from the

FRAME.