This chapter contains the following sections:
Introduction
Modules
Modules and Symbols
Sections
Section Names
Absolute Sections
Section Examples
Scopes
Scope Example
Scopes and Symbol Names
Complex software projects often are divided into smaller program units. These subprograms may be written by a team of programmers in parallel, or they may be programs written for a previous development effort that are going to be reused. The TASKING assembler provides directives to subdivide a program into smaller parts, modules. Symbols can be defined local to a module, so that symbol names can be used without regard to the symbols in other modules. Code and data can be organized in separate sections. These sections can be named in such a way that different modules can implement different parts of these sections. These section can be located in memory by the locator so that concerns about memory placement are postponed until after the assembly process. By using separate modules, a module can be changed without re-assembling the other modules. This speeds up the turnaround time during the development process.
Modules are the separate implementation parts of a project. Each module is defined in a separate file. A module is assembled separately from other modules. By using the INCLUDE directive common definitions and macros can be included in each module. Using the mk563 utility the module file and include file dependencies can be specified so only the correct modules are re-assembled after changes to one of the files the modules depend upon.
A module can use symbols defined in other modules and in the module itself. Symbols defined in a module can be local (other modules cannot access it) or global (other modules have access to it). Symbols outside of a module can be defined with the EXTERN directive. Local symbols are symbols defined by the LOCAL directive, '_'-local labels (underscore labels) or symbols defined with an SET, GSET or EQU directive. Global symbols are either normal labels (non '_'-labels), or symbols explicitly defined global with the GLOBAL directive.
The '_'-labels have their own scoping rules. The scope of such a label is bounded by the surrounding non '_'-label definitions. The TASKING assembler also supports the scoping as imposed by the SECTION and ENDSEC directives, see below for a description. The linker checks the definition of symbols with their reference. For example, when a symbol is defined in a module as a label in P memory and is referred to from another module as a label in X memory an error message will be given. The assembler will perform these checks per module.
Sections are relocatable blocks of code and data. Sections are defined with the ORG directive and can be named. A section may have attributes to instruct the locator to place it on a predefined starting address, in near or internal memory or that it may be overlaid with another section. See the ORG directive discussion for a complete description of all possible attributes. Different ORGs with the same name designate the same section, so the attributes of all these ORGs must match. The linker will check this between different modules and emits an error message if the attributes do not match. The linker will also concatenate all matching section definitions into one section. So, all ".text" sections generated by the compiler will be linked into one big ".text" chunk which will be located in one piece. By using this naming scheme it is possible to collect all pieces of code or data belonging together into one bigger section during the linking phase. An ORG directive referring to an earlier defined section is called a continuation. Only the memory type, optional name and optional location counter can be mentioned.
The assembler generates object files in relocatable IEEE-695 object format. The assembler groups units of code and data in the object file using sections. All relocatable information is related to the start address of a section. The locator assigns absolute addresses to sections. A section is the smallest unit of code or data that can be moved to a specific address in memory after assembling a source file. The compiler requires that the assembler supports several different sections with appropriate attributes to assign specific characteristics to those sections. (section with read only data, sections with code, etc.)
A section must be declared before it can be used. The ORG directive declares a section with its attributes. A section name can be any identifier. The '@' character is not allowed in regular section names. The assembler and linker use this character to create overlayable sections. This is explained below.
The memory spaces can be:
mem : This defines in which memory space (X, Y, L, P or E) the section is located. Currently the E memory space is not supported.
The attributes can be:
attrib | Description |
FAR | long addressable |
NEAR | short addressable |
INTERNAL | internal memory, same as mapping 'I' |
EXTERNAL | external memory, same as mapping 'E' |
OVERLAY | section must have an overlay name, implies 'scratch' |
ABSOLUTE | obsolete, the absolute-location must be an absolute expression |
BSS | clear section during startup |
CONST | initialize during download, do not generate copy table entry |
INIT | initialize section during startup (this attribute is required for P data sections) |
MAX | common, overlay with other parts with the same name, is implicitly a type of 'scratch' and 'overlay' |
SCRATCH | not filled, not cleared on startup. Section can only contain DS directives, no DC or the like |
Table 3-1: Section attributes
Unless disabled, the startup code in the tool chain has to clear BSS sections. These sections contain data space allocations for which no initializers have been specified. BSS sections are zeroed (cleared) at program startup. Sections can be excluded from this initialization with the SCRATCH attribute.
The INIT attribute defines that the section contains initialization data, which is copied from ROM to RAM at program startup. Sections with the CONST attribute, however, are initialized during download.
By default P sections are executable and data memory sections are initialized. The INIT, BSS, CONST and SCRATCH attributes are mutually exclusive. The following table shows the effect of these attributes on section initialization.
Attribute | P section | X, Y, L section |
- | executable code, download only | data, init on startup from copy table |
INIT | data, init on startup from copy table | data, init on startup from copy table |
BSS | data, clear on startup | data, clear on startup |
CONST | data, download only | data, download only |
SCRATCH | data, no action | data, no action |
Table 3-2: Attribute effect on sections
Sections with the NEAR attribute must be allocated in the first 64 words of memory of the DSP56xxx . The locator produces a warning if a section with the NEAR attribute cannot be allocated in this area.
The MAX attribute changes the way the linker determines the section size. Normally the linker determines the section size by accumulating the contents and the sizes of sections with the same name in different object modules. When sections with the same name occur in different object modules with the MAX attribute, the linker generates a section of which the size is the maximum of the sizes in the individual object modules. The MAX attribute applies to BSS sections only.
A section becomes overlayable by specifying the OVERLAY attribute. Only BSS sections are overlayable. The assembler reports an error if it finds the attribute combined with sections of other types. Because it is useless to initialize overlaid sections at program startup time (code using overlaid data cannot assume that the data is in the defined state upon first use), the SCRATCH attribute is defined implicitly when OVERLAY is specified. Overlayable section names are composed as follows:
ORG X,"OVLN@nfunc", BSS, OVERLAY, NEAR: ^ ^ | | pool name function name
The linker overlays sections with the same pool name. To decide whether BSS sections can be overlaid, the linker builds a call graph. Data in sections belonging to functions that call each other cannot be overlaid. The compiler generates pseudo instructions (CALLS) with information for the linker to build this call graph. The CALLS pseudo has the following syntax:
If the function main() has overlayable data allocations in the zero page and calls nfunc(), the following sections and call information will be generated:
ORG X,"OVLN@nfunc", BSS, OVERLAY, NEAR: ORG X,"OVLN@main", BSS, OVERLAY, NEAR: CALLS 'main', 'nfunc'
This type of overlaying is done by the linker using a
call graph, but it is also possible to specify overlaying by the locator using
the DELFEE language. See the DELFEE keywords contiguous and overlay in Appendix G
for more information.
Sections become absolute when an address has been specified in the declaration. The assembler generates information in the object file which instructs the locator to put the section contents at the specified address. It is not allowed to make an overlayable section absolute. The assembler reports an error if an absolute location (abs-loc) is used in combination with the OVERLAY section attribute.
After a section has been declared, it can be re-activated with the ORG directive:
ORG X,".STRING",FAR: ORG X,".STRING": _l001: DCB "hello world"
All instructions and pseudos which generate data or code must be within an active section. The assembler emits a warning if code or data starts without a section definition and activation.
For reasons of compatibility with the Motorola CLAS assembler the TASKING assemblers for the DSP56xxx also accepts the Motorola CLAS section definition. See the description of the ORG directive in the chapter Assembler Directives for more information.
Absolute sections (i.e. ORG directives with a start address) may only be continued in the defining module (continuation). When such a section is defined in the same manner in another module, the locator will try to place the two sections at the same address. This results in a locator error. When an absolute section is defined in more than one module, the section must be defined relocatable and its starting address must be defined in the locator description (.dsc) file. Overlay sections may not be defined absolute.
Some examples of the ORG directive are as follows:
ORG P:$1000
ORG P:
ORG X,".xabs":$40
ORG X,".xabs":
ORG P,".text":
ORG X,".xdata",BSS:
ORG X,".xdata":
ORG X,".xovl@f",OVERLAY:
The assembler also supports, on module level, the scoping mechanism as introduced by the Motorola SECTION directive. A block enclosed in a SECTION/ENDSEC pair is called a scope. Scopes are called sections by Motorola, but we use the term section to designate a relocatable block of code or data, as defined by an ORG directive. Symbols defined within a scope are only accessible from within the scope they are defined in or from scopes nested within the defining scope. Exceptions are symbols that, within a scope, are defined GLOBAL. They can be referenced from any other scope.
The scoping rule can be understood by thoroughly examining the following code fragment, in the comment there is a reference to which symbol the instruction is referencing. Symbol references are described by the construction "scope.symbol".
; @(#)RESOLVE.ASM 1.1 95/06/26 ; LABEL RESOLVING TEST ; ; This should assemble without errors or warnings ; ORG P: LOCAL BW ; (BW local to this module, ; not exported to object) BW: ; (Label on module level, ; defined local, will not ; be exported to object) JMP S_FW ; S.S_FW (was defined global within ; scope S) JMP FW ; FW (forward reference to label ; on module level) JMP TWICE ; TWICE (forward reference to label ; on module level)
SECTION S GLOBAL S_FW S_FW ; = S.S_FW (global label, will be promoted ; to module level, is exported ; as S_FW) JMP TWICE ; S.TWICE (forward reference to section ; label) TWICE ; = S.TWICE (definition hides global symbol ; TWICE) JMP TWICE ; S.TWICE (backward reference to section ; label) FW ; = S.FW (definition hides global symbol ; FW) JMP FW ; S.FW (backward reference to section ; label) JMP BW ; BW (backward reference to label ; on module level) ENDSEC
TWICE ; = TWICE (label on module level, is ; exported by this module) JMP TWICE ; TWICE (backward reference) FW ; = FW (label on module level, is ; exported by this module) JMP BW ; BW (backward reference)
; AND NOW SOME STACKING OF SECTIONS.... JMP LAB ; LAB (forward reference to label ; on module level) SECTION P JMP LAB ; P.LAB (forward reference to label ; defined in the current scope) SECTION Q JMP LAB ; Q.LAB (forward reference to local ; defined in the current scope) SECTION R JMP LAB ; P.LAB (Q.LAB is local so invisible ; to scope R, P.LAB is visible) ENDSEC ENDSEC LAB ; = P.LAB ENDSEC
SECTION Q LOCAL LAB ; (Define lab local to scope Q, ; invisible from other scopes) LAB ; = Q.LAB (Local scope label LAB) ENDSEC LAB ; = LAB (Global label LAB, exported ; to object)
; AND NOW SOME '_'-LABELS: _LAB JMP _LAB ; Link to this _LAB ; (_LAB is not exported to object) NO_LAB JMP _LAB ; Link to next _LAB ; (NO_LAB is exported to object, ; previous _LAB is forgotten) _LAB ; (New definition of _LAB) END
Symbols defined in a scope are prefixed with the scope name, when these symbols are written to the object file they are transformed into legal assembler symbols.
For example:
SECTION sec label: ; defines sec.label ENDSEC
The symbol "sec.label" will be transformed to the symbol "sec_label" before it is written to the object file. This can give name collisions with an already defined symbol "sec_label". In that case, after renaming, the string "_x" will be repeatedly appended to the symbol name until the name is unique within the current module. An exception to this rule is symbols that are defined GLOBAL within a scope. They are promoted to the module level, outside any other scope, and placed in the object file as-is, without any pre- or post-fixing of section names or "_x" strings.