PRB: Using /NT with /AS or /AC May Result in L2003 Link Error

ID Number: Q72702

6.00 6.00a 6.00ax | 6.00 6.00a

MS-DOS | OS/2

buglist6.00 buglist6.00a buglist6.00ax fixlist7.00

Summary:

SYMPTOMS

If the /NT (name code segments) switch is used to compile a small

(/AS) or compact (/AC) model program with the Microsoft C Compiler

version 6.0, 6.0a, or 6.0ax, it may not be possible to link the

resulting object module. Instead, the linker may return the

following error message:

error L2003: intersegment self-relative fix-up at 'number' in

segment 'segment'

RESOLUTION

To work around the problem, use the alloc_text pragma to place the

functions in the module in a particular segment.

STATUS

Microsoft has confirmed this to be a problem in C versions 6.0,

6.0a, and 6.0ax. This problem was corrected in C/C++ version 7.0.

More Information:

When /NT is used with the small or compact memory model, the compiler

incorrectly assumes that the named code segment is the default code

segment. As a result, the compiler creates near calls to helper

functions that may be required in the code.

These helper functions all start with "__aN..." (__aNchkstk, __aNlmul,

__aNfmuls, and so forth). When LINK tries to build the .EXE file, it

determines that the symbols are not in the default code segment for

that module (so they cannot be called with a near call), and the above

error message is generated.

For instance, if the sample code below is compiled and linked as

indicated, the following error messages will be generated by the

linker:

test2.obj(test2.c) : error L2003: intersegment self-relative fix-up at

3C in segment MYSEG target external '__aNfstsp'

test2.obj(test2.c) : error L2003: intersegment self-relative fix-up at

35 in segment MYSEG target external '__aNfsts'

test2.obj(test2.c) : error L2003: intersegment self-relative fix-up at

2F in segment MYSEG target external '__aNfmuls'

test2.obj(test2.c) : error L2003: intersegment self-relative fix-up at

29 in segment MYSEG target external '__aNflds'

test2.obj(test2.c) : error L2003: intersegment self-relative fix-up at

23 in segment MYSEG target external '__aNchkstk'

test2.obj(test2.c) : error L2003: intersegment self-relative fix-up at

16 in segment MYSEG target external '__aNlmul'

test2.obj(test2.c) : error L2003: intersegment self-relative fix-up at

7 in segment MYSEG target external '__aNchkstk'

This problem does not exist if the module is compiled with the quick

compile option (/qc) or if the alloc_text pragma is used to identify

the segments in which to place the functions. The use of alloc_text is

illustrated in a comment in the second .C module below.

Sample Code

-----------

Compile the two modules, TEST1.C and TEST2.C, (below) as specified and

then link as follows:

LINK /NOI TEST1+TEST2,,,/NOD:SLIBCA SLIBCAP, TEST.DEF;

TEST1.C

-------

/* Compile options needed: /c /FPa /AS (or /AC)

*/

int _cdecl printf(const char *, ...);

int main(void);

long _far func1(long, long);

float _far func2(float, float);

int main(void)

{

long c;

float d;

c = func1(100l, 200l);

if (c != 100l * 200l)

{

printf("Failed\n");

return(1);

}

d = func2(100.0f, 200.0f);

if (d!= (float)100.0f * 200.0f)

{

printf("Failed\n");

return(1);

}

printf("Passed\n");

return(0);

}

TEST2.C

-------

/* Compile options needed: /NTmyseg /c /FPa /AS (or /AC)

*/

long far func1(long, long);

float far func2(float d, float e);

/* Uncomment the following line to work around the problem. */

// #pragma alloc_text(myseg, func1, func2)

long far func1(long a, long b)

{

long c;

c = a*b;

return c;

}

float far func2(float d, float e)

{

float f;

f = d * e;

return(f);

}

TEST.DEF

--------

; Module definition file required for linking.

NAME TEST

SEGMENTS

MYSEG class 'CODE' LOADONCALL

Additional reference words: 6.00 6.00a 6.00ax