Basic Memory Model: Determining Segment Sizes with LINK /MAP (37030)



The information in this article applies to:

  • Microsoft Visual Basic for MS-DOS
  • Microsoft QuickBASIC 4.0
  • Microsoft QuickBASIC 4.0b
  • Microsoft QuickBASIC 4.5
  • Microsoft BASIC Compiler for MS-DOS and OS/2 6.0
  • Microsoft BASIC Compiler for MS-DOS and OS/2 6.0b
  • Microsoft Basic Professional Development System (PDS) for MS-DOS and MS OS/2 7.0

This article was previously published under Q37030

SUMMARY

Visual Basic for MS-DOS uses a medium memory model. With this particular memory model, a program may contain multiple code segments (up to 64K per module) and one 64K shared data segment (known as DGROUP). The exceptions to this in Visual Basic for MS-DOS are far strings, which can be thought of as special string data segments outside the default data segment, and huge (larger than 64K) dynamic arrays supported in the far heap. The space that is not used by the code and DGROUP at run time is left for allocation of dynamic and huge dynamic arrays.

The LINK .MAP file can be used to determine the size of the code segment(s) and the static portion of the DGROUP segment, as shown below. However, the FRE function is easier to use than the LINK .MAP file for getting information about data allocation.

MORE INFORMATION

This information is also included with the Help file provided with the Standard and Professional Editions of Microsoft Visual Basic for MS-DOS, version 1.0.

Note that allocating longer variable-length strings may consume more DGROUP space at run time than is indicated by the initial, static DGROUP allocation shown in the LINK .MAP file.

Rather than using the LINK .MAP file, a better method of determining data usage is to invoke the FRE function within a program at run time. The STACK function returns the amount of dynamic space free for strings and dynamic arrays in DGROUP. FRE(-1) returns the amount of space free for dynamic arrays in the far heap.

To generate a link map, use the /MAP switch for the linker (LINK /MAP). The following link map is generated by linking a module called DOG.OBJ and is explained further below:
 Start  Stop   Length Name                   Class
 00000H 0003DH 0003EH DOG_CODE               BC_CODE
 00040H 029A3H 02964H RTCODE                 CODE
 029B0H 02CA0H 002F1H _TEXT                  CODE
 02CA1H 036ABH 00A0BH LMEM                   CODE
 036ACH 036DDH 00032H LOADRTM                CODE
 036E0H 0374EH 0006FH FOCODE                 CODE
 03750H 03750H 00000H C_ETEXT                ENDCODE
 03750H 03750H 00000H FDATA                  FAR_DATA
 03750H 03757H 00008H FAR_HDR                FAR_MSG
 03758H 03D7DH 00626H FAR_MSG                FAR_MSG
 03D7EH 03D7FH 00002H FAR_PAD                FAR_MSG
 03D80H 03D80H 00001H FAR_EPAD               FAR_MSG
 03D90H 03D9FH 00010H NULL                   BEGDATA
 03DA0H 03DA7H 00008H NULL2                  BEGDATA
 03DB0H 03DB0H 00000H BR_DATA                BLANK
 03DB0H 03DDFH 00030H BR_SKYS                BLANK
 03DE0H 03DE0H 00000H COMMON                 BLANK
 03DE0H 03DE5H 00006H BC_DATA                BC_VARS
 03DE6H 03DE7H 00002H NMALLOC                BC_VARS
 03DE8H 03DE9H 00002H ENMALLOC               BC_VARS
 03DEAH 03DEAH 00000H BC_FT                  BC_SEGS
 03DF0H 03DFDH 0000EH BC_CN                  BC_SEGS
 03E00H 03E02H 00003H BC_DS                  BC_SEGS
 03E04H 03E04H 00000H BC_SAB                 BC_SEGS
 03E04H 03E07H 00004H BC_SA                  BC_SEGS
 03E08H 03E0BH 00004H BC_SAE                 BC_SEGS
 03E0CH 03E37H 0002CH CONST                  DATA
 03E38H 03EF0H 000B9H _BSS                   DATA
 03EF2H 04465H 00574H _DATA                  DATA
 04466H 04466H 00000H XIB                    DATA
 04466H 04469H 00004H XI                     DATA
 0446AH 0446AH 00000H XIE                    DATA
 0446AH 0446AH 00000H XECIB                  DATA
 0446AH 0446AH 00000H XECI                   DATA
 0446AH 0446AH 00000H XECIE                  DATA
 0446AH 0446AH 00000H XCB                    DATA
 0446AH 0446DH 00004H XC                     DATA
 0446EH 0446EH 00000H XCE                    DATA
 0446EH 0447BH 0000EH CDATA                  DATA
 0447CH 04489H 0000EH DBDATA                 DATA
 0448AH 0448BH 00002H XIQC                   DATA
 0448CH 0448CH 00000H XIFB                   DATA
 0448CH 0448CH 00000H XIF                    DATA
 0448CH 0448CH 00000H XIFE                   DATA
 0448CH 0448CH 00000H XPB                    DATA
 0448CH 0448CH 00000H XP                     DATA
 0448CH 0448CH 00000H XPE                    DATA
 0448CH 0448CH 00000H XCFB                   DATA
 0448CH 0448CH 00000H XCFCRT                 DATA
 0448CH 0448CH 00000H XCF                    DATA
 0448CH 0448CH 00000H XCFE                   DATA
 0448CH 0448CH 00000H XIFCB                  DATA
 0448CH 0448CH 00000H XIFU                   DATA
 0448CH 0448CH 00000H XIFL                   DATA
 0448CH 0448CH 00000H XIFM                   DATA
 0448CH 0448CH 00000H XIFCE                  DATA
 0448CH 0448CH 00000H BC_DATA                BC_DATA
 0448CH 0448CH 00000H _BSS                   BSS
 0448CH 0448CH 00000H XOB                    BSS
 0448CH 0448CH 00000H XO                     BSS
 0448CH 0448CH 00000H XOE                    BSS
 0448CH 0448CH 00000H XOFB                   BSS
 0448CH 0448CH 00000H XOF                    BSS
 0448CH 0448CH 00000H XOFE                   BSS
 04490H 0528FH 00E00H STACK                  STACK

 Origin   Group
 03D9:0   DGROUP
 0375:0   FMGROUP
				
In the above example, a source module called DOG.BAS was compiled and linked, resulting in a code segment name of DOG_CODE, which is limited to a maximum of 64K in size (if other compiler limitations are not exceeded first). DOG_CODE has the class name of BC_CODE. If your code module is approaching 64K in size, you should break it into SUBprogram and/or FUNCTION procedures in separate modules that can be compiled separately and then linked with the main module.

The first seven lines in the above map are the code segments. Each segment named can be up to 64K in size. Their classes are usually BC_CODE, CODE, and ENDCODE.

The Origin section at the bottom of the link map tells you the position where the default data segment (DGROUP) starts, relative to the start of the .EXE code. The sum of the length of the items in DGROUP cannot exceed 64K. Items in DGROUP start at 03D9:0 in the above map [which means offset 0 from the (16-byte) paragraph address 03D9 hex].

FMGROUP, whose origin is listed at the bottom of the link map as well, is used for allocation tables and messages relating to far data, such as variable length strings and dynamic arrays. Space for strings and arrays in the far heap is not allocated until run time.

Note that the addresses given in the link map are not absolute load addresses -- instead, they are relative to the start of the code in the relocatable .EXE file. Only at run time does MS-DOS decide the absolute address where the .EXE program is loaded in memory. The VARPTR, VARSEG, SSEG, and SADD functions can then be used within a Visual Basic for MS-DOS program to determine absolute addresses of variables and arrays at run time.

Modification Type:MinorLast Reviewed:8/16/2005
Keywords:KB37030