This chapter contains the following sections:
Overview
Introduction
Naming Conventions
Invocation
Link51 Options
Link51 Controls
Overview link51 Controls
Linking Controls
Locating Controls
Listing Controls
Detailed Description of Controls
Link51 Output
Bank Switching
Writing Your Own Bank Switch Routine
Common Area
Locating Algorithm
Restrictions
Ressources
Linker Special Labels
Linking with Libraries
Linking OMF51 Objects and Libraries
Case Sensitivity
Object Format
Module Selection
Backward Referencing in Libraries
Linker Implementation
Cross-Reference
Object Format
Controls
Module Selection
Backward Referencing in Libraries
The next sections describe how the 8051 linker program link51 works. The installation of this program is part of the installation of the assembler package 'TASKING 8051 Cross-Assembler'. We first introduce the linker by describing its functions globally and giving some basic examples. Later on a more elaborate description of all the features follows.
The OMF51 format mentioned in this chapter is the standard OMF51 object and OMF51 library format as defined by Intel.
link51 is a program that reads one or more object modules created by the assembler asm51 or object modules in OMF51 format and locates them in memory. Object modules can be in ordinary files or in object libraries. The format of the object modules can be in the a.out file format, or the OMF51 format. Modules in the a.out format have been created by the assembler as a separate module in an individual object file. Afterwards you can put these files in a library with the library manager (ar51 ).
For linking OMF51 objects and OMF51
libraries, see section 9.11,
Linking OMF51 Objects and Libraries.
The following diagram shows the input files and output files of the linker:
Figure 9-1: Linker
Many programs are often too long or too complex to be in one single unit. As programs in a single unit grow too large they become more difficult to maintain. An application broken down in small functional units is easier to code and debug. Translation of these programs into load modules is faster than their counterpart in one module.
The linker translates relocatable object modules into absolute load files. This lets you write programs that are (partially) made up of modules that can be placed anywhere in memory. Doing so, reusability of your code increases. Those programs that fulfill a specific task needed in many applications (I/O-routines) can be placed in a library, thus making them available for many programmers.
link51 performs the following tasks:
A segment is a unit of code or data in memory. Every segment has a type: the memory type in which it is located. A segment can be absolute: in the assembler source text an absolute address is bound to the segment. A relocatable segment is a segment that is defined in the assembler text without an address. For these segments the final location in memory is determined by the linker. A segment can be split up into parts each of which can reside in different modules in the application. These parts are called partial segments.
A module is a unit of code that can be located in a file. A module can contain one or more segments. The terms object module and object file are used as equivalent terms.
An object library is a file containing a number of object modules. The linker includes only those parts from a library that have been referred to from other modules.
A program can be created out of one single module or out of a number of modules. A part of the program can be in a library.
The linker can be called in three different ways:
When you use a UNIX shell (C-shell, Bourne shell), options containing special characters (such as '( )' ) must be enclosed with "". The invocations for UNIX and PC are the same, except for the -? option in the C-shell:
link51 "-?" or link51 -\?
In the first invocation all relevant information is specified on the command line. The second and third invocation of link51 demonstrate the use of a linker command file.
You can use options and controls to steer the linking/locating process. Options can appear in any order. Options start with a '-'. Only the -lx option is position dependent. Options that require a filename can be separated by a space or not: -oname is equal to -o name. Options and controls are explained in detail in the following sections.
ifile can be any object file or library. These input files must be separated by commas ','. The first instance where two items on the command line follow each other without being separated by a comma and not preceded by a minus sign (an option) is taken to be the start of the optional part of the command line (the controls). Input files must be valid names of disk files of the operating system you are working with.
The output file is a disk file containing the absolute output of the linker. The name of the file can be specified on the command line using the -o option or with the TO control. The name following this keyword is used as output file. If no output file is specified the linker uses the name of the first input file to create an output filename. The basename of this filename is used as an output filename. So if no output filename is specified, the file created by the linker will have no extension. Because of this, all input filenames must have an extension. Offending this necessity leads to a fatal error reported by the linker.
Applications consisting of a large number of object modules require a lot of typing if the linker must be started and all the module names (and options) must be entered. Instead of typing all the information on the command line, it can be put into a file (using spaces, tabs and newlines freely).
The filename can start with a '@'-sign or '_'-sign. This filename can be used in the linker invocation as the one and only argument. The reason of the two different prefixes is that the '@'-sign is special to certain operating systems. The linker internally removes the '@'- sign or '_'-sign to work better with 'make' utilities.
The contents of this file is not read as an object module, but the linker processes it as if it had been typed on the command line.
1. link51 mod1.obj, mod2.obj -o demo1.out
In the example above the plain object files mod1.obj and mod2.obj are linked into the output file demo1.out.
2. link51 mod1.obj, mod2.obj, float.lib, util.lib -o demo2.out
This example show the use of libraries. Besides the plain object files mod1.obj and mod2.obj two library files are specified. The linker includes only those modules from the library that have been referenced in the first two object files.
3. link51 @lcmd
The linker first tries to read the file @lcmd as a text file. If this fails, the linker tries to read the file lcmd as a text file. If this fails also, the linker issues a warning message. If the file was found, the contents of this file are interpreted as command line information. e.g.:
@lcmd: mod1.obj, mod2.obj, mod3.obj, mod4.obj, mod5.obj, mod6.obj -o demo3.out ramsize( 080H )
After reading the file @lcmd the six object modules are linked in the output file demo3.out. The control ramsize informs the linker about the size of on-chip ram.
4. link51 _lcmd
The linker first tries to read the file _lcmd as a text file. If this fails, the linker tries to read the file lcmd as a text file. If this fails also, the linker issues a warning message. If the file was found, the content of this file is interpreted as command line information. e.g.:
_lcmd: mod1.obj, mod2.obj, mod3.obj, float.lib, util.lib -o demo4.out ramsize( 080H )
After reading the file _lcmd the three object modules and two libraries are linked in the output file demo4.out. The control ramsize informs the linker about the size of on-chip ram.
The linker recognizes the following options:
Option | Description | ||||||||
-? | Display invocation syntax | ||||||||
-Aarchitecture | Select libraries specifically designed for a particular architecture | ||||||||
-Ldirectory | Additional search path for libraries | ||||||||
-V | Display version header only | ||||||||
-banks num | Specify the number of code banks | ||||||||
-common size | Specify the size of the common area used for code bank switching | ||||||||
-enum | Convert warning num to an error | ||||||||
-err file |
Redirect error messages to file
-ffile |
Read command line information from file, | '-' means stdin
-lx |
Link library file x.lib |
-o file |
Specify name of output file |
-wnum |
Convert error num to a warning | |
Table 9-1: Options summary
A detailed description of the option is given below.
With options that can be set from within EDE, you will
find a mouse icon that describes the corresponding action.
-?
Display an explanation of the invocation syntax at stdout.
link51 -?
From the Project menu, select Project Options... Expand the Linker entry and select Miscellaneous. Add the option to the Additional linker options/controls field.
-Aarchitecture
The name of the subdirectory to search for architecture specific libraries.
Specify a subdirectory of the library directory to search for architecture specific libraries. If a library is not found in the architecture subdirectory, it is searched for in the library directory itself.
To specify the directory for libraries specifically designed for dallas_aa, enter:
link51 -Adallas_aa x.obj y.obj
From the Project menu, select Project Options... Expand the Linker entry and select Bank Switching. Enter the number of banks in the Number of code banks field.
-banks number
The number of code banks.
Specify the number of code banks used.
To specify that you have 2 code memory banks, enter:
link51 test.obj -banks 2 -otest.out
See section 9.8
, Bank Switching, for more details.
From the Project menu, select Project Options... Expand the Linker entry and select Bank Switching. Enter a size in the Size of common area (starting at code address 0) field.
-common size
The size of the common area.
Specify the size of the common area used for code bank switching.
To specify that you have 2 code memory banks and that the common area is at code address range 0 - 8000H, enter:
link51 test.obj -banks 2 -common 8000H -otest.out
See section 9.8
, Bank Switching, for more details.
-enum
The warning message number.
Convert the specified warning message to an error.
To convert warning 6 to an error, enter:
link51 test.obj -e6 -otest.out
In EDE this option is not so useful. If you would use
this option you would not see the error messages in the
Build tab.
-err filename
An error output filename.
The linker redirects error messages to a file with the name filename.
To write errors to the file test.elk instead of stderr, enter:
link51 test.obj -err test.elk -otest.out
From the Project menu, select Project Options... Expand the Linker entry and select Miscellaneous. Add the option to the Additional linker options/controls field.
-f file
A filename for command line processing. The filename "-" may be used to denote standard input.
Use file for command line processing. To get around the limits on the size of the command line, it is possible to use command files. These command files contain the options that could not be part of the real command line. Command files can also be generated on the fly, for example by the make utility.
More than one -f option is allowed.
Some simple rules apply to the format of the command file:
1. It is possible to have multiple arguments on the same line in the command file.
2. To include whitespace in the argument, surround the argument with either single or double quotes.
3. If single or double quotes are to be used inside a quoted argument, we have to go by the following rules:
a. If the embedded quotes are only single or double quotes, use the opposite quote around the argument. Thus, if a argument should contain a double quote, surround the argument with single quotes.
b. If both types of quotes are used, we have to split the argument in such a way that each embedded quote is surrounded by the opposite type of quote.
Example:
"This has a single quote ' embedded"
or
'This has a double quote " embedded'
or
'This has a double quote " and \ a single quote '"' embedded"
4. Some operating systems impose limits on the length of lines within a text file. To circumvent this limitation it is possible to use continuation lines. These lines end with a backslash and newline. In a quoted argument, continuation lines will be appended without stripping any whitespace on the next line. For non-quoted arguments, all whitespace on the next line will be stripped.
Example:
"This is a continuation \ line" -> "This is a continuation line" control(file1(mode,type),\ file2(type)) -> control(file1(mode,type),file2(type))
5. It is possible to nest command line files up to 25 levels.
Suppose the file mycmds contains the following line:
-err test.err test.obj
The command line can now be:
link51 -f mycmds
From the Project menu, select Directories... Add one or more directory paths to the Library Files Path field.
-Ldirectory
The name of the directory to search for libraries.
Add directory to the list of directories that are searched for libraries. Directories specified with -L are searched before the standard directories specified by the environment variable CC51LIB and the ../lib directory relative to the directory where the executable is located. You can use the -L option more than once to add several directories to the search path for libraries. The search path is created in the same order as in which the directories are specified on the command line.
link51 -Lc:\cc51\examples\lib test.obj -lc51s
From the Project menu, select Project Options... Expand the Linker entry and select Linking. Enable one or more of the Libraries
options. It depends on the settings in the C Compiler entry which options are available.
-lx
A string to form the name of the library x.lib.
Link library x.lib, where x is a string. The linker first searches for libraries in any directories specified with -Ldirectory, then in the standard directories specified with the environment variable CC51LIB and finally in the ../lib directory relative to the directory where the executable is located.
This option is position dependent (see section
9.10, Linking with Libraries).
To link library c51s.lib after the user object and library are linked, enter:
link51 myobj.obj,mylib.lib -lc51s
-ofilename
An output filename.
a.out
Use filename as output filename of the linker. If this option is omitted, the default filename is a.out.
To create the output file test.out instead of a.out, enter:
link51 test.obj -otest.out
-V
With this option you can display the version header of the linker. This option must be the only argument of link51. Other options are ignored. The linker exits after displaying the version header.
link51 -V
TASKING 8051 linker/locator vx.yrz Build nnn Copyright years Altium BV Serial# 00000000
-wnum
The error message number.
Convert the specified error message to a warning.
To convert error 114 to a warning, enter:
link51 test.obj -w114 -otest.out
The behavior of the linker can be influenced with controls. The linker can be informed how it has to do certain tasks. A control is accepted only once. If it is found twice the linker displays an error message and aborts. There are three types of controls:
Control | Abbr | Cl | Def | Description |
BANK ( bank, segment [( address )] ) | BA | Loc | Locate code segment in specified bank. | |
BIT ( segment [( address )] [,...] ) | BI | Loc | Locate bitaddressable on-chip data | |
CASE NOCASE |
CA NOCA | G | CA |
Scan symbols case sensitive. Scan symbols as is. |
CHECK NOCHECK |
CH NOCH | G |
NOCH |
Check for empty segments. Accept empty segments. |
CODE ( segment [( address )] [,...] ) | CO | Loc | Locate code memory. | |
COMMON ( segment [( address )] ) | CM | Loc | Locate code segment in common area. | |
DATA ( segment [( address )] [,...] ) | DA | Loc | Locate direct addressable data. | |
DEBUGLINES NODEBUGLINES |
DL NODL | D | DL |
Generate debug line records. No debug line records. |
DEBUGPUBLICS NODEBUGPUBLICS |
DP NODP | D | DP |
Generate public symbol records. No public symbol records. |
DEBUGSYMBOLS NODEBUGSYMBOLS |
DS NODS | D | DS |
Generate local symbol records. No local symbol records. |
FBRANCH ( c_segm [,c_segm ]...) | FB | Mem | Designate branch for overlaying. | |
FUNCTIONOVERLAY ( c_segm >| ] c_segm ,...) | FO | Mem | No overlay | Overlay code segments. |
GRAPH(number) | GR | List | GR(0) | Generate a call graph. |
IDATA ( segment [( address )] [,...] ) | ID | Loc | Locate indirect addressable on-chip ram. | |
LINES NOLINES |
LI NOLI | List |
NOLI |
Line numbers in map file. No line number information. |
MAP NOMAP |
MA NOMA | List | MA |
Produce a link map in list file. Inhibit production of map. |
NAME(module-name) | NA | G | - | No action. |
OVERLAY ( module >| ] module ,...) NOOVERLAY |
OL NOOL | Mem | NOOL |
Overlay segments in modules. Do not overlay. |
PAGEWIDTH(width) | PW | List | 78 | Set map file page width. |
PRECEDE ( segment [( address )] [,...] ) | PC | Loc | Locate precedence on-chip ram. | |
PRINT [(filename)] NOPRINT |
PR NOPR | List | PR |
Print link map to named file. Do not generate list file. |
PUBLICS NOPUBLICS |
PL NOPL | List |
NOPL |
Public symbols in map file. No public symbols in map file. |
RAMSIZE(size) | RS | Mem | 128 | Specify internal data ram size. |
RESERVE(memtype(address,address) [,...] ) memtype is: BIT DATA IDATA XDATA CODE |
RE BI DA ID XD CO | Mem |
Reserve memory space for: bit addressable data Direct addressable data indirect addressable on-chip ram external ram code memory | |
STACK ( segment [( address )] [,...] ) | ST | Loc | Locate indirect addressable on-chip ram. | |
SYMBOLS NOSYMBOLS |
SB NOSB | List |
NOSB |
Local symbol information in map file. No local symbols in map file. |
XDATA ( segment [( address )] [,...] ) | XD | Loc | Locate external ram. | |
XPAGE ( page_number ) | XP | Mem | 0 | Specify auxiliary page. |
Abbr: Abbreviation of the control Cl: Class, type of control, D means a debugging control G means a miscellaneous linking control List means a listing control Loc means a locate control Mem means a memory control Def: Default control |
Table 9-2: link51 controls
Linking controls can be divided into:
DEBUGLINES / NODEBUGLINES
DEBUGPUBLICS / NODEBUGPUBLICS
DEBUGSYMBOLS / NODEBUGSYMBOLS
FBRANCH
FUNCTIONOVERLAY
OVERLAY / NOOVERLAY
RAMSIZE
RESERVE
XPAGE
CASE / NOCASE
CHECK / NOCHECK
NAME
Locating controls give you the opportunity to control the strategy the linker uses to determine the absolute addresses of segments. You can use these controls to inform the linker about the order in which the segments should be located or at which absolute address a specific segment should be placed.
If locating controls are omitted the linker uses the following list of rules to locate the segments (ordered by precedence, grouped by memory type).
- Absolute segments BIT, DATA, IDATA and register banks.
- Segments in the PRECEDE control in the invocation line.
- Segments in a BIT control in the invocation line.
- Relocatable DATA segments with the BIT-ADDRESSABLE attribute.
- Other relocatable BIT-segments.
- Segments in a DATA control in the invocation line.
- Other DATA segments.
- Segments in the IDATA control in the invocation line.
- Other IDATA segments, except '?STACK'.
- Segments in the STACK control in the invocation line.
- ?STACK if it is
in IDATA and not mentioned in another control.
- Absolute external data segments.
- Segments in the XDATA control in the invocation line.
- External data segment having the SHORT attribute.
- Other relocatable
XDATA segments.
- Absolute code segments.
- Segments in the CODE control in the invocation line.
- Other relocatable code segments.
- CODE segments with the ROMDATA attribute.
The locating controls have the following general format:
where segment is:
The address part in the segment specification is optional. Mentioning a segment name without an address in a control, forces the linker to locate the segment at a specific time, according to the rules mentioned above, but leaving it up to the linker to determine the optimal starting address of the segment. If absolute addresses are given in a control, they should be in ascending order.
The following locating controls are supported:
Control | Abbr | Address range | Address space | Segment type |
PRECEDE | PC | 00H - 2FH | on-chip ram | DATA, IDATA |
BIT | BI | 00H - 7FH | bitaddressable on-chip data space |
BIT, DATA, IDATA |
DATA | DA | 00H - 7FH | on-chip data directly addressable | DATA, IDATA |
IDATA | ID | 00H - 0FFH | indirectly addressable on-chip ram | IDATA |
STACK | ST | 00H - 0FFH | indirectly addressable on-chip ram | IDATA |
XDATA | XD | 00H - 0FFFFH | external RAM | XDATA |
CODE | CO | 00H - 0FFFFH | code memory | CODE |
Table 9-3: Locate controls
Bitaddressable segments are only allowed in the BIT-control. On all other places where data segments are mentioned, they must be unit-aligned. (A unit is the minimal addressable memory part in a segment: a bit in bit segments, a byte in all other segments)
Segment addresses in the BIT-control must be dividable by eight if the segment involved is of type DATA (bit addressable). If the segment is of bit-type, any bitaddress is allowed. The valid range for on-chip ram addresses (IDATA) depends on the physical limits of the target processor. The default size is 128. This value can be altered with the RAMSIZE control.
The STACK-control is meant to inform the linker which IDATA-segments must be located in the upper part of the IDATA space. The start address for the first segment in the STACK control is the first free memory location above the highest located segment in on-chip RAM.
The segment ?STACK is located in the uppermost part of IDATA space if it is not mentioned in any previous control. A segment with this name is created within the startup code of the C-51 compiler.
Data segments placed with any locating control are located
as non-overlayable segments. This influences optimal locating by link51 when using the
OVERLAY /
FUNCTIONOVERLAY controls.
1. link51 mod1.obj, mod2.obj, mod3.obj to demo4.out
precede( m1_seg, m2_seg ) bit( m2_dseg( 10H ))
This example shows the precede control. The linker first locates the segment m1_seg in memory. m2_seg is put at the next address available succeeding m1_seg. The segment m2_dseg is located at bitaddress 10H. This equals byte address 22H.
2. link51 mod1.obj, mod2.obj, mod3.obj to demo5.out
code( m1_cseg( 2000H ), m2_cseg, m3_cseg )
In the example above the code control is used to locate all the code segments above 2000H.
3. link51 mod1.obj, mod2.obj, mod3.obj to demo6.out stack( m_stk )
Here the stack control is used to force the IDATA segment m_stk in the upper part of on-chip ram. m_stk is located in the highest internal ram locations of all IDATA segments.
The linker can produce a map file. In a map file a memory map of the linked segments in the application is given. The listing controls allow you to specify what the contents of the map file should look like.
The following listing controls are recognized by the linker:
With controls that can be set from within EDE, you will
find a mouse icon that describes the corresponding action.
BANK( bank, segment [ (address) ] )
From the Project menu, select Project Options... Expand the Linker entry and select Bank Switching. Enter a bank number, a code segment and optionally a locate address in the
Locate segments in specific code bank field.
The bank number, a segment name with optionally a start address.
BA
Locating control
-
Locate a segment in a specified code bank in memory (address range 0-0FFFFH). The segment must be of type CODE. You can specify more than one BANK control.
The address part in the segment specification is optional. Mentioning a segment name without an address, forces the linker to locate the segment at a specific time, according to the default locating algorithm, but leaving it up to the linker to determine the optimal starting address of the segment. If absolute addresses are given, they should be in ascending order.
link51 mod1.obj, mod2.obj -banks 2 -o demo.out bank( 1,m1_seg( 2000H )) bank( 2,m2_seg ) ; Locate code segment m1_seg in bank 1 at 2000H and ; locate segment m2_seg in bank 2
Section 9.6.3
, Locating Controls, describes the default locating algorithm and contains an overview
of the locating controls.
See section 9.8
, Bank Switching, for more details.
BIT( segment [ (address) ] [, segment [ (address) ] ]... )
From the Project menu, select Project Options... Expand the Linker entry and select Segments. Enter the segment and optionally a locate address in the Locate BIT segments field.
A segment name with optionally a start address.
BI
Locating control
-
Locate a segment in the bitaddressable on-chip data space (address range 0-7FH). The segment must be of type BIT, DATA or IDATA. Segment addresses in the BIT control must be dividable by eight if the segment involved is of type DATA (bit addressable). If the segment is of type BIT, any bitaddress is allowed.
The address part in the segment specification is optional. Mentioning a segment name without an address, forces the linker to locate the segment at a specific time, according to the default locating algorithm, but leaving it up to the linker to determine the optimal starting address of the segment. If absolute addresses are given, they should be in ascending order.
The valid range for on-chip ram addresses (IDATA) depends on the physical limits of the target processor. The default size is 128. This value can be altered with the RAMSIZE control.
link51 mod1.obj,mod2.obj -o test.out bit( m2_dseg(10H)) ; locate segment m2_dseg in bitaddressable memory ; starting at bitaddress 10H (is byte-address 22H)
Section 9.6.3
, Locating Controls, describes the default locating algorithm and contains an overview
of the locating controls.
CASE/NOCASE
From the Project menu, select Project Options... Expand the Linker entry and select Linking. Enable or disable the option Link case sensitive.
CA/NOCA
Linking control
CASE
With these controls, the linker can be told to treat case sensitive or not. Programs written in the 'C' language produce case sensitive symbols.
link51 x.obj case ; link51 in case sensitive mode
CHECK/NOCHECK
CH/NOCH
Linking control
NOCHECK
The linker accepts empty relocatable segments. These segments have no code bytes or a segment size greater than 0. Labels may have been defined in the segment, but they do not influence the segment size. link51 accepts these segments.
For compatibility reasons (Intel does not accept them) you can use the CHECK control to reject these segments if they occur. The default setting is NOCHECK. Empty segments are located at the address, following the highest addresses occupied, in the memory space they belong to.
link51 x.obj check ; link51 rejects empty segments
CODE( segment [ (address) ] [, segment [ (address) ] ]... )
From the Project menu, select Project Options... Expand the Linker entry and select Segments. Enter a code segment and optionally a locate address in the Locate CODE segments field.
A segment name with optionally a start address.
CO
Locating control
-
Locate a segment in code memory (address range 0-0FFFFH). The segment must be of type CODE.
The address part in the segment specification is optional. Mentioning a segment name without an address, forces the linker to locate the segment at a specific time, according to the default locating algorithm, but leaving it up to the linker to determine the optimal starting address of the segment. If absolute addresses are given, they should be in ascending order.
link51 mod1.obj, mod2.obj, mod3.obj -o demo5.out code( m1_cseg( 2000H ), m2_cseg, m3_cseg ) ; Locate all the code segments above 2000H
Section 9.6.3
, Locating Controls, describes the default locating algorithm and contains an overview
of the locating controls.
COMMON( segment [ (address) ] )
From the Project menu, select Project Options... Expand the Linker entry and select Bank Switching. Enter the segments to be located in the common area and optionally enter a locate address in the Locate segments common area field.
A segment name with optionally a start address.
CM
Locating control
-
Locate a segment in common area in memory. The segment must be of type CODE. You can specify more than one COMMON control.
The address part in the segment specification is optional. Mentioning a segment name without an address, forces the linker to locate the segment at a specific time, according to the default locating algorithm, but leaving it up to the linker to determine the optimal starting address of the segment. If absolute addresses are given, they should be in ascending order.
link51 mod1.obj, mod2.obj, mod3.obj -banks 2 -o demo.out bank( 1,m1_seg( 2000H )) common(m2_seg) common(m3_seg) ; Locate code segment m1_seg in bank 1 at 2000H and ; locate segments m2_seg and m3_seg in the common area
Section 9.6.3
, Locating Controls, describes the default locating algorithm and contains an overview
of the locating controls.
See section 9.8
, Bank Switching, for more details.
DATA( segment [ (address) ] [, segment [ (address) ] ]... )
From the Project menu, select Project Options... Expand the Linker entry and select Segments. Enter the segment and optionally a locate address in the Locate DATA segments field.
A segment name with optionally a start address.
DA
Locating control
-
Locate a segment in the direct addressable on-chip data space (address range 0-7FH). The segment must be of type DATA or IDATA.
The address part in the segment specification is optional. Mentioning a segment name without an address, forces the linker to locate the segment at a specific time, according to the default locating algorithm, but leaving it up to the linker to determine the optimal starting address of the segment. If absolute addresses are given, they should be in ascending order.
The valid range for on-chip ram addresses (IDATA) depends on the physical limits of the target processor. The default size is 128. This value can be altered with the RAMSIZE control.
link51 mod1.obj,mod2.obj -o test.out data( m1_dseg(30H)) ; locate segment m1_dseg in DATA memory starting at address 30H
Section 9.6.3
, Locating Controls, describes the default locating algorithm and contains an overview
of the locating controls.
DEBUGLINES/NODEBUGLINES
From the Project menu, select Project Options... Expand the Linker entry and select Linking. Enable or disable the option Include debug information for LINE records.
DL/NODL
Linking control
DEBUGLINES
The C compiler generates '?LINE'-pseudos in the generated assembly text. The assembler creates line-records in the object file for each occurrence of this pseudo. If you want to suppress generation of these records in the absolute output file, the NODEBUGLINES control will do so.
DEBUGPUBLICS/NODEBUGPUBLICS
From the Project menu, select Project Options... Expand the Linker entry and select Linking. Enable or disable the option Include debug information for PUBLIC symbols.
DP/NODP
Linking control
DEBUGPUBLICS
This control causes the linker to generate public symbol definition records in the output file. NODEBUGPUBLICS disables the generation of public symbol records.
DEBUGSYMBOLS/NODEBUGSYMBOLS
From the Project menu, select Project Options... Expand the Linker entry and select Linking. Enable or disable the option Include debug information for LOCAL symbols.
DS/NODS
Linking control
DEBUGSYMBOLS
This control can be used to start generation of symbolic information in the output file. DEBUGSYMBOLS starts generation of symbol records for local symbols. The negated version causes the linker to suppress the output of these records.
FBRANCH( c_segm [,c_segm ]... )
From the Project menu, select Project Options... Expand the Linker entry and select Overlay. Fill in the code segments that have to be handled as separate branches by the overlaying mechanism.
One or more CODE segment names.
FB
Linking control
-
During execution of the main loop interrupts may occur at any moment. This means that data areas used by the interrupt routines may not be overlayed with data areas used by the main thread. The linker already prevents overlaying of interrupts that use a different register bank than the default one. However, for interrupts using the default register bank it is required to use the FBRANCH control in order for the linker to prevent overlaying of their data areas.
Suppose we have defined the following interrupt function in module int0.c: _interrupt(1) void ISR0( void ); then the following command will prevent data areas used by the interrupt routine to be overlayed by ones used by the main routine.
link51 main.obj int0.obj -o demo.out FO FBRANCH(INT0_ISR0)
FUNCTIONOVERLAY[( calling-scheme [, calling-scheme ]... )]
From the Project menu, select Project Options... Expand the Linker entry and select Overlay. Select the Function based overlaying for C radio button or select
User specified overlaying and fill in your own overlay control.
A calling-scheme is defined as follows:
where,
FO
Linking control
Function overlay is off
The control FUNCTIONOVERLAY cannot be used in combination with the control OVERLAY.
The control FUNCTIONOVERLAY can be used for C-51 only.
link51 is an overlaying linker. This means that the linker is capable of overlaying segments within the same range in internal ram locations. Two segments are overlayable if the following conditions are met:
Two code segments both using variables located in internal ram can use the same address ranges for these variables if the two code segments are disjoint. That means they do not call each other directly or indirectly. Because only code segments can reference each other, while the used data space for these code segments should be overlaid, we need to know which code segment uses which data segment. Therefore, link51 uses a naming convention for all segments.
The name of the code segment using overlayable data should be named func_PR. For function overlay, all used data segments for this code segment should be declared "overlay" and use the following naming convention.
All data segments not using this naming convention will not be overlaid.
If two code segments do not call each other, their variables are not 'alive' at the same time, so they can be put on the same addresses. The smallest unit of internal data that is possibly overlaid is a segment. The TASKING assembler asm51 gives you the opportunity to declare a segment to be overlayable.
Calls from one code segment to another can be detected by the linker via relocatable "call" instructions in the object files. If these connections between code segments exist the linker will not overlay the data segments declared to these code segments.
A problem can arise if the calls are invisible for the linker. Then it might be that two data segments are overlaid and used at the same time by the application. This will lead to unpredictable behavior of the program. For this purpose the call-indicators can be used. They are meant to inform the linker about the calling structure in the application the linker cannot deduce from the relocatable "call" instructions of the object files. Note that the call-indicator does not overrule the normal call it is an add-on to the existing call structure.
When using FUNCTIONOVERLAY recursive relations between segments may not occur. When the linker finds such a relation, it will abort immediately. Note however that a segment making a call to itself is allowed by the linker. link51 also has an option to print a call graph to show the relation between the code segments (See the GRAPH control).
1. link51 mod1.obj,mod2.obj,mod3.obj to demo4.out functionoverlay
2. link51 mod1.obj,mod2.obj,mod3.obj to demo5.out "functionoverlay( segm3 ] mseg1 )"
3. link51 mod1.obj,mod2.obj,mod3.obj to demo6.out "functionoverlay( segm1 ] * )"
The first example shows the simplest use of the functionoverlay control. All segments in the three modules that are marked overlayable and conform to the requirements mentioned above will be overlaid by the linker.
The second example shows how to inform the linker that there is a connection between two segments out of any of the modules, which is invisible for the linker. Suppose there is code like:
jmp @a + dptr
in some code segment (e.g. C51 produces this for indirect function calls). If dptr contains an address of a code label in the first segment, the code above is an indirect jump into a second segment. If there are no other call references between these two segments the linker might erroneously conclude that overlaying data segments of these functions is correct. This is not true. To prevent the linker from making this false assumption, the functionoverlay control is used to explicitly inform the linker about the calling structure of segm1 and segm3 (SEGM1_PR and SEGM3_PR).
The third example shows how to prevent the linker from overlaying any segment in internal data mentioned in the first segment. The 'segm1 > *' (all hosts), 'segm1 ] *' (PC/UNIX) calling-scheme causes the linker to assume references between segm1 and any other code segment in the application. This causes no overlay for segm1. The assumption is made that the calling scheme 'segm1 > *' or 'segm1 ] *' does not introduce recursion. This is not checked.
link51 only recognizes
'CALL' instructions between segments, not 'JMP' instructions. Within a complete C-51 application,
the only 'JMP' instruction causing incorrect overlaying of data is generated when using indirect function calls within the C-application (as described earlier).
When handwritten assembly code is linked together with C- generated code, all segment crossing 'JMP' instructions should be defined to the linker with the functionoverlay command. Otherwise no guarantee can be given that overlaying of data is correct.
See also the controls
FBRANCH and
OVERLAY.
GRAPH[(number)]
From the Project menu, select Project Options... Expand the Linker entry and select Map File. Enable the option Include C-51 function call graph in map file and optionally enable the option Use extensive version of C-51 function call graph.
Optionally the number 0 or 1.
GR
Listing control
GRAPH(0)
This control only has effect when the control FUNCTIONOVERLAY is specified too. A call graph of the code segments will be reported. One of two styles can be chosen:
GRAPH or GRAPH(0):
GRAPH(1):
link51 module1.obj functionoverlay graph
IDATA( segment [ (address) ] [, segment [ (address) ] ]... )
From the Project menu, select Project Options... Expand the Linker entry and select Segments. Enter the segment and optionally a locate address in the Locate IDATA segments field.
A segment name with optionally a start address.
ID
Locating control
-
Locate a segment in the indirectly addressable on-chip data space (address range 0-FFH). The segment must be of type IDATA.
The address part in the segment specification is optional. Mentioning a segment name without an address, forces the linker to locate the segment at a specific time, according to the default locating algorithm, but leaving it up to the linker to determine the optimal starting address of the segment. If absolute addresses are given, they should be in ascending order.
The valid range for on-chip ram addresses (IDATA) depends on the physical limits of the target processor. The default size is 128. This value can be altered with the RAMSIZE control.
link51 mod1.obj,mod2.obj -o test.out idata( m1_seg(80H)) ; locate segment m1_seg in IDATA memory starting at address 80H
Section 9.6.3
, Locating Controls, describes the default locating algorithm and contains an overview
of the locating controls.
LINES/NOLINES
From the Project menu, select Project Options... Expand the Linker entry and select Map File. Enable or disable the option Include LINE information in the map file.
LI/NOLI
Listing control
NOLINES
The LINES control enables printing of line numbers with their corresponding addresses in the link map file. NOLINES prevents the printing of line numbers.
link51 x.obj lines ; generate line numbers in map file
MAP/NOMAP
From the Project menu, select Project Options... Expand the Linker entry and select Map File. Enable or disable the option Include a link map in the map file.
MA/NOMA
Listing control
MAP
This control can be used to enable or prevent generation of a link map in the map file. Print must be enabled. If NOPRINT is specified the MAP-setting is ignored.
link51 x.obj nomap ; do not generate link map in map file
NAME(module-name)
NA
Linking control
-
The name control is recognized by the linker but no further action is taken. The module name is not written into the output file. The output filename uniquely identifies the output of the linker.
OVERLAY ( calling-scheme [, calling-scheme
]... )
NOOVERLAY
From the Project menu, select Project Options... Expand the Linker entry and select Overlay. Select the User specified overlaying radio button and fill in your own
overlay control.
A calling-scheme is defined as follows:
where,
OL/NOOL
Linking control
NOOVERLAY
The control OVERLAY cannot be used in combination with the control FUNCTIONOVERLAY.
link51 is an overlaying linker. This means that the linker is capable of overlaying segments within the same range in internal ram locations. Two segments are overlayable if the following conditions are met:
Two modules both using variables located in internal ram can use the same address ranges for these variables if the two modules are disjoint. That means they do not call each other directly or indirectly.
If two modules do not call each other, their variables are not 'alive' at the same time, so they can be put on the same addresses. The smallest unit of internal data that is possibly overlaid is a segment. The TASKING assembler asm51 gives you the opportunity to declare a segment to be overlayable.
Calls or jumps from one module to another can be detected by the linker via PUBLIC/EXTERNAL declaration of code labels. If these connections between modules exist, the linker will not overlay the segments declared in these modules.
A problem can arise if the calls are invisible for the linker. Then it might be that two data segments are overlaid and used at the same time by the application. This will lead to unpredictable behavior of the program. For this purpose the call-indicators can be used. They are meant to inform the linker about the calling structure in the application the linker cannot deduce from the PUBLIC/EXTERNAL definitions.
1. link51 mod1.obj,mod2.obj,mod3.obj to demo4.out overlay
2. link51 mod1.obj,mod2.obj,mod3.obj to demo5.out "overlay( mod3 ] mod1 )"
3. link51 mod1.obj,mod2.obj,mod3.obj to demo6.out "overlay( mod1 ] * )"
The first example shows the simplest use of the overlay control. All segments in the three modules that are marked overlayable and conform to the requirements mentioned above will be overlaid by the linker.
The second example shows how to inform the linker that there is a connection between the third and the first module which is invisible for the linker. Suppose in the third module there is code like:
jmp @a + dptr
If dptr contains an address of a code label in the first module, the code above is an indirect jump into the first module. If there are no other PUBLIC/EXTERNAL references between these two modules the linker might erroneously conclude that overlaying data segments of these modules is correct. This is not true. To prevent the linker from making this false assumption, the overlay control is used to explicitly inform the linker about the calling structure of mod1 and mod3.
The third example shows how to prevent the linker from overlaying any segment in internal data mentioned in the first module. The 'mod1 > *' calling-scheme causes the linker to assume references between mod1 and any other module in the application. This causes no overlay for the segments in the first module.
PAGEWIDTH(width)
From the Project menu, select Project Options... Expand the Linker entry and select Map File. Enter the number of characters in the Page width (characters per line) field.
The number of characters per line.
PW
Listing control
PAGEWIDTH(78)
The PAGEWIDTH control specifies how many characters can be written on one line in the map file. Any value between 72 and 132 is allowed. The default value is 78.
link51 module1.obj print( mod1.l51 ) pw( 80 ) ; set page width to 80 characters
PRECEDE( segment [ (address) ] [, segment [ (address) ] ]... )
From the Project menu, select Project Options... Expand the Linker entry and select Segments. Enter the segment and optionally a locate address in the User PRECEDE control field.
A segment name with optionally a start address.
PC
Locating control
-
Locate a segment in the on-chip data space (address range 0-2FH). The segment must be of type DATA or IDATA.
The address part in the segment specification is optional. Mentioning a segment name without an address, forces the linker to locate the segment at a specific time, according to the default locating algorithm, but leaving it up to the linker to determine the optimal starting address of the segment. If absolute addresses are given, they should be in ascending order.
The valid range for on-chip ram addresses (IDATA) depends on the physical limits of the target processor. The default size is 128. This value can be altered with the RAMSIZE control.
link51 mod1.obj, mod2.obj, mod3.obj -o demo.out precede( m1_seg, m2_seg ) bit( m2_dseg( 10H ))
The linker first locates the segment m1_seg in memory. m2_seg is put at the next address available succeeding m1_seg. The segment m2_dseg is located at bitaddress 10H. This equals byte address 22H.
Section 9.6.3
, Locating Controls, describes the default locating algorithm and contains an overview
of the locating controls.
PRINT[(file)]/NOPRINT
From the Project menu, select Project Options... Expand the Linker entry and select Map File. Enable or disable the option Generate a linker map file (.l51).
Optionally the map file name.
PR/NOPR
Listing control
PRINT(output-file.l51)
The filename determines where the listing information will be written. The filename may be omitted. Then the map filename is created from the basename of the output file and the extension .l51. NOPRINT prevents the linker from generating any listing information. The default setting is PRINT.
link51 module1.obj print( mod1.l51 ) ; map filename is mod1.l51
PUBLICS /NOPUBLICS
From the Project menu, select Project Options... Expand the Linker entry and select Map File. Enable or disable the option Include PUBLIC symbol information in the map file.
PL / NOPL
Listing control
NOPUBLICS
The PUBLICS control enables printing of public symbol names and their corresponding addresses in the link map file. NOPUBLICS disables the printing of public symbols.
link51 x.obj y.obj pl ; print public symbols in link map file x.l51
RAMSIZE(size)
From the Project menu, select Project Options... Expand the Processor entry and select Memory. Select a size in the On-chip data RAM size (0-256) field.
The size of internal RAM (in bytes).
RS
Linking control
RAMSIZE( 128 )
The ramsize control can be used to inform the linker about the size of internal data ram (in bytes). The default value assumed by the linker is 128 (8051 on-chip ram size). The valid range for ramsize values is 128-256.
link51 x.obj rs( 200 ) ; link51 assumes an internal RAM of 200 bytes
RESERVE(memory_type( start_address, end_address )
[, memory_type( start_address,
end_address ) ]... )
From the Project menu, select Project Options... Expand the Linker entry and select Reserved Areas. Enter an address range in the Reserve memory_type memory field. You can enter several address ranges by separating them with a semi-colon ';'.
Optionally, enable the option Reserve first byte of XDATA to prevent pointers on address 0.
A memory type and an address range to be excluded from locating. memory_type can be:
RE
Linking control
All memory is assumed available.
With this control you can tell the linker which address ranges should not be used to locate code or data.
When a certain part of code/ram space is already in use by a previously programmed EPROM or by some other hardware, use this control to specify the linker it cannot use the specified address space.
A specified address range (start_address, end_address) is reserved starting at the first given address up to and including the last address specified. It is possible to specify multiple address ranges for the same memory type.
link51 mod1.obj,mod2.obj -o demo.out reserve(xdata( 0, 400H ), code( 0, 2000H ), code( 3000H, 4000H ) )
External RAM addresses 0 up to and including address 400H cannot be used. Code range 0 up to 2000H and the code range 3000H up to 4000H also cannot be used.
Absolute segments and segments placed with a linker control
are placed into the reserved areas when specified. In this case a memory overlap is reported.
STACK( segment [ (address) ] [, segment [ (address) ] ]... )
A segment name with optionally a start address.
ST
Locating control
-
Locate a segment in the indirectly addressable on-chip data space (address range 0-0FFH). The segment must be of type IDATA.
The STACK control is meant to inform the linker which IDATA segments must be located in the upper part of the IDATA space. The start address for the first segment in the STACK control is the first free memory location above the highest located segment in on-chip RAM.
The segment ?STACK is located in the uppermost part of IDATA space if it is not mentioned in any previous control. A segment with this name is created within the startup code of the C-51 compiler.
The address part in the segment specification is optional. Mentioning a segment name without an address, forces the linker to locate the segment at a specific time, according to the default locating algorithm, but leaving it up to the linker to determine the optimal starting address of the segment. If absolute addresses are given, they should be in ascending order.
The valid range for on-chip ram addresses (IDATA) depends on the physical limits of the target processor. The default size is 128. This value can be altered with the RAMSIZE control.
link51 mod1.obj, mod2.obj, mod3.obj -o demo.out stack( m_stk )
The stack control is used to force the IDATA segment m_stk in the upper part of on-chip ram. m_stk is located in the highest internal ram locations of all IDATA segments.
Section 9.6.3
, Locating Controls, describes the default locating algorithm and contains an overview
of the locating controls.
SYMBOLS/NOSYMBOLS
From the Project menu, select Project Options... Expand the Linker entry and select Map File. Enable or disable the option Include LOCAL symbol information in the map file.
SB/NOSB
Listing control
NOSYMBOLS
With the SYMBOLS control local symbols can be printed in the link map file. NOSYMBOLS prevents the printing of local symbols.
link51 x.obj y.obj sb ; print local symbols in link map file x.l51
TO filename
An output filename.
a.out
Use filename as output filename of the linker. If this control is omitted, the default filename is a.out. This is the same as the -o option.
To create the output file test.out instead of a.out, enter:
link51 test.obj to test.out
XDATA( segment [ (address) ] [, segment [ (address) ] ]... )
From the Project menu, select Project Options... Expand the Linker entry and select Segments. Enter the segment and optionally a locate address in the Locate XDATA segments field.
A segment name with optionally a start address.
XD
Locating control
-
Locate a segment in external RAM space (address range 0-0FFFFH). The segment must be of type XDATA.
The address part in the segment specification is optional. Mentioning a segment name without an address, forces the linker to locate the segment at a specific time, according to the default locating algorithm, but leaving it up to the linker to determine the optimal starting address of the segment. If absolute addresses are given, they should be in ascending order.
link51 mod1.obj,mod2.obj -o test.out xdata( m1_seg(0FF00H), m2_seg) ; locate segments m1_seg and m2_seg in XDATA memory ; starting at address 0FF00H
Section 9.6.3
, Locating Controls, describes the default locating algorithm and contains an overview
of the locating controls.
XPAGE(page_number)
From the Project menu, select Project Options... Expand the Processor entry and select Startup Code. Enter a page number in the External RAM page to be used for paged data (_pdat) field.
A value between 0 and 255.
XP
Linking control
0
XDATA segments having the SHORT attribute will be located in a page of auxiliary memory. By default the first 256-bytes page will be used for this. You can use the XPAGE control to specify a different page in auxiliary memory.
The linker creates different sorts of output:
The map file contains information about the absolute object file produced by the linker. The following items appear in the map file:
The name for the map file is derived from the output filename. The extension (if present) of this filename is substituted by '.l51'.
link51 supports code memory banking. With this technique you can extend your code memory beyond 64Kb.
When specifying multiple banks the linker automatically locates segments across all code banks. The problem that arises is when a function in one bank needs to call a function that is located in another bank. Since the 8051 instruction set supports no 24-bit call or jump instruction another solution is needed. The linker solves the problem by automatically inserting a piece of code called a 'stub routine'. Instead of calling the remote function directly, the stub routine is called. The stub routine on its turn calls a special bank switching routine, passing the new code bank number and the offset of the remote function within that bank. The bank switching routine then switches to the new code bank, calls the function, and on return switches back to the original bank and function. An example of a possible stub code implementation is shown below.
__LK_STUB SEGMENT CODE RSEG __LK_STUB __LK_STUB_ENTRY: MOV DPTR,#__LK_FUNCTION_ADDRESS ; pass 16-bit offset MOV A,#__LK_FUNCTION_BANK ; pass new code bank number JMP __LK_BANKSWITCH
Each time this stub routine is inserted the variable __LK_FUNCTION_ADDRESS will be replaced with the 16-bit offset address of the function to be called. The same way the variable __LK_FUNCTION_BANK will be replaced with the 8-bit number of the bank of the function to be called.
All inter-code bank calls will be detected by the linker and will be replaced with such a stub routine. When the same remote function is called several times from one bank the same stub code will be used.
When there is a large number of inter-code bank calls the number of stubs will also be large. Therefore, it is best to keep the stub routine as small as possible. So, instead of the previous stub routine another method can be used. Instead of calling one general routine passing the new code bank, the bank switch routine will be copied for every bank, and the specific routine will be called that switches to the required new bank.
__LK_STUB SEGMENT CODE RSEG __LK_STUB __LK_STUB_ENTRY: MOV DPTR,#__LK_FUNCTION_ADDRESS JMP __LK_BANKSWITCH ; switch to code bank
When this stub routine is used, the linker automatically detects that the variable containing the code bank (__LK_FUNCTION_BANK) is missing. This results in the bank switching routine being copied for each code bank. This implementation is the default used in the C library.
In this case the variable __LK_FUNCTION_ADDRESS will be replaced in the same way as with the previous stub routine. However, the JMP to __LK_BANKSWITCH will be replaced with a JMP to the right bank switch routine (for example __LK_BANKSWITCH3 to switch to bank 3).
If you use EDE, you can enter bank switching information
in the Linker | Bank Switching entry of the Project | Project Options... dialog.
Each stub routine calls a routine which performs the actual code bank switch and calls the function in the new code bank. The following example shows an implementation of such a bank switching routine. The example assumes SFR P1 is used to select the code bank. If you use another hardware implementation, adapt the routine likewise.
__BANKSW SEGMENT CODE RSEG __BANKSW __LK_BANKSWITCH: PUSH P1 ; push current bank CALL _bankswitch POP P1 ; switch back to original bank RET _bankswitch: MOV P1,#__LK_FUNCTION_BANK ; switch to new bank CLR A JMP @A+DPTR
The stub routine and bank switching routine are present
in the file stub.src in the lib/src directory. This file is part of the C library.
If you do not want the default bank switch routines you can write your own routines. You have to rewrite two routines at the most, the stub routine and the bank switch routine. You can use the file stub.src in the lib/src directory as a starting point.
Requirements:
- use a unique segment name that is not used elsewhere.
- the segment must contain the label __LK_STUB_ENTRY. This label is the entry jumped to.
- the segment must contain the variable __LK_FUNCTION_ADDRESS. This variable will contain the 16-bit offset of the remote function.
As explained before, there are two possible bank switch methods. The one selected depends on the variable __LK_FUNCTION_BANK. You can use it in the stub routine as a reference to the code bank of the remote function.
More likely than replacing the default stub routine is changing the bank switch routine. The default routine assumes that SFR P1 is used to select the code bank. If you have an implementation that uses a different SFR, or one that uses, for instance, an external data address you have to rewrite the bank switching routine.
Requirements:
- use a unique segment name that is not used elsewhere.
- if the stub routine does not contain the variable __LK_FUNCTION_BANK then use it in this routine. In that case the routine will be copied for each code bank, and in each copy the variable will be replaced with the (8-bit) code bank number.
Because interrupts can occur at any moment, the interrupt vectors need to be present in each code bank. This is also the case for the bank switching routine, which must be reachable at any time from any code bank. Instead of copying all this code in every bank, you have to define an area that is independent of the selected code bank, the so-called 'common area'. Since a function in the common area can be called from any code bank without a stub-routine it can also be used to locate functions that are called very often, decreasing both access time as well as code size.
You can use the
-common option to define the size of the common area (starting at code address 0). You
can define segments to be located in the common area with the
COMMON
control.
When multiple code banks are used the linker will use a different locating algorithm than the default for Code segments (see section 9.6.3, Locating Controls).
The following locating order is used:
1. Absolute code segments
2. Segments in the COMMON control in the invocation line
3. Segments in the BANK control in the invocation line
4. ROMDATA segments
5. Related segments, linked due to code relocatables
6. Other relocatable segments
When a certain CODE segment has references to another segment, for instance to access constant ROM data, it is absolutely necessary they are located in the same bank. If not, then accessing the constant ROM data will result in data in the wrong bank being retreived.
Since the program counter of the 8051 is only 16-bits it is not possible to cross 64Kb borders without using the bank switching routine. The linker therefore ensures that no segment will be located over a 64Kb boundary.
Using function pointers in combination with code bank switching might result in erroneous situations. Since function pointers are 16-bit and can be passed between functions the linker is not able to determine the connection between caller and callee. This does not mean you cannot use function pointers at all, however you have to make sure any function using function pointers is in the same code bank as the function that might be called from it.
You have take into account the following resources when using code bank switching:
The linker/locator assigns addresses to the following labels when they are referenced:
__LK_B_name : Begin of segment name.
__LK_E_name : End of segment name.
__LK_L_name : Size of segment name.
You can use these labels to obtain the addresses of segment name in a program.
The relation between the three labels is:
__LK_E_name = __LK_B_name + __LK_L_name
If you are linking from libraries, only those objects you need are extracted from the library. This implies that if you invoke the linker like:
link51 mylib.lib
nothing is linked and no output file will be produced, because there are no unresolved symbols when the linker searches through mylib.lib.
The position of the library is important, if you specify:
link51 -lc51s myobj.obj, mylib.lib
the linker starts with searching the system library c51s.lib without unresolved symbols, thus no module will be extracted. After that, the user object and library are linked. When finished, all symbols from the C library remain unresolved. So, the correct invocation is:
link51 myobj.obj, mylib.lib -lc51s
All symbols which remain unresolved after linking myobj.obj and mylib.lib will be searched for in the system library c51s.lib.
The link order for objects, user libraries and system
libraries is the order in which they appear at the command line. Objects are always linked, object modules in libraries are only linked if they are needed.
This section describes how to link OMF51 object modules with link51. In particular the following subjects will be discussed:
In the OMF51 object format, all symbols are always in uppercase. In the a.out object format, symbols are case sensitive, i.e. names in uppercase and lowercase are distinct. The TASKING 'C' compiler generates case sensitive labels (the C-function names in the C-library are all in lowercase).
So, a call from an object module in OMF51 format to a function which is in the library of the TASKING 'C' compiler would be impossible. Therefore it may be required to use the 'NOCASE' control of the linker.
Be aware that this control may introduce naming conflicts. In the 'C' language it is possible to create two functions with the names 'func' and 'Func', which are distinct names. When using the 'NOCASE' control the names will not be distinct anymore.
The linker link51 reads files in the OMF51 format used by Intel compilers, assemblers and linkers. The output file of link51 is always in the COFF-a.out-format described before. Libraries in the OMF51 library format are accepted also.
High level language debug information represented in the OMF51 object module will not be placed in the output file of the linker link51. High level source debugging can only be done on modules compiled with the TASKING C-51 compiler.
Assembly level debug information is present. All symbols are placed in the output file of link51.
The a.out file created by the linker can be formatted to the OMF51 format with use of the formatter omf51 .
The Intel linker allows you to select one or more object modules from an object file. The TASKING linker link51 does not support this feature. If an object file containing more than one object module is linked with link51, only the first module in this file is linked.
The TASKING linker link51 has no library manager for OMF51 libraries. Only existing libraries can be linked.
The linker scans the object modules in a library in the first phase. If a module contains public definitions of symbols that are unresolved so far, the module is included in the second phase.
If such a module itself contains external symbols, the definitions of these symbols are first sought in the modules that are found in the remainder of the library. After the linker has scanned all modules in the library, it does a rescan of the library to see if one of the previous modules contains a definition of the symbols. Only when no more external definitions can be resolved by any object module in the library, the linker will continue with the next file (object or library) given in the linker command.
Rescanning of a library is not done for libraries in
a.out format.
This chapter describes the differences between the Intel linker and the TASKING link51. In particular the following subjects are discussed:
The cross-reference control is not supported by link51.
The linker link51 generates files in modified version of the COFF-a.out-format used by other TCP assemblers and linkers. Linker input files may be in the a.out format or the OMF51 format (see section 9.11, Linking OMF51 Objects and Libraries).
The COFF-a.out format has been extended to support the Intel defined assembly language constructs. The changes of the format can be found in the extension part of the format description.
The extension records are redefined to store new information in the relocatable object files and the absolute load files. Utility programs like dmp51 and the object conversion programs have been adapted to be able to read these files.
In the TCP-a.out file format the contents of the code part of a section is always contiguous, so there is at most one code part per section. The Intel approach towards segments is different: there may be discontiguous ranges in an absolute segment.
The dmp51 program displays the contents of a segment as one contiguous block. On each line a code address is prepended. This address is calculated from the segment start address and the relative offset in the code-part. In the new format this approach is not suitable. The start addresses displayed by dmp51 may therefore be not correct.
A number of controls, defined by Intel, are not supported by link51. The linker gives a warning and the control is ignored. The following controls are not supported:
The Intel linker allows you to select one or more object modules from an object file. This is useful because the OMF51-file format allows you to append a number of object modules into a file without use of a library manager. The TASKING a.out format is built upon the assumption that an object file contains one object module. The selection of modules from a file becomes meaningless in this approach.
The TASKING linker link51 is shipped with a library manager (ar51 ). This archiver allows you to build libraries of object modules. The manual page of this program, enclosed in this manual, describes how this should be done.
The linker scans the object modules in a library in the first phase. If a module contains public definitions of symbols that are unresolved so far, the module is included in the second phase.
If such a module itself contains external symbol declarations, the definitions of these symbols are sought only in the modules that are found in the remainder of the library. The linker does not rescan the library to see if one of the previous modules contains the definition of the symbol. Creating a library, you should pay attention to the order the archiver puts the modules in.