MPLAB XC8 PIC Assembler User Guide 50002974
MPLAB XC8 PIC Assembler User Guide 50002974
Important:
All documentation becomes dated, and Development Tools manuals are no exception. Our tools and
documentation are constantly evolving to meet customer needs, so some actual dialogs and/or tool
descriptions may differ from those in this document. Please refer to our website (www.microchip.com/) to
obtain the latest version of the PDF document.
Documents are identified with a DS number located on the bottom of each page. The DS format is
DS<DocumentNumber><Version>, where <DocumentNumber> is an 8-digit number and <Version> is an
uppercase letter.
For the most up-to-date information, find help for your tool at onlinedocs.microchip.com/.
1. Preface....................................................................................................................................................4
1.1. Conventions Used in This Guide..................................................................................................4
1.2. Recommended Reading...............................................................................................................5
2. Assembler Overview............................................................................................................................... 6
2.1. Device Description....................................................................................................................... 6
2.2. Compatible Development Tools....................................................................................................6
3. Assembler Driver.....................................................................................................................................7
3.1. Single-step Assembly...................................................................................................................7
3.2. Multi-step Assembly..................................................................................................................... 7
3.3. Long Command Lines.................................................................................................................. 8
3.4. Assembler Option Descriptions.................................................................................................... 8
3.5. MPLAB X IDE Integration...........................................................................................................19
5. Assembler Features.............................................................................................................................. 59
5.1. Preprocessor Directives............................................................................................................. 59
5.2. Assembler-provided Psects........................................................................................................60
5.3. Default Linker Classes............................................................................................................... 60
5.4. Linker-Defined Symbols............................................................................................................. 62
5.5. Using a Compiled Stack............................................................................................................. 62
5.6. Assembly List Files.....................................................................................................................63
6. Linker.................................................................................................................................................... 66
6.1. Operation....................................................................................................................................66
6.2. Psects and Relocation................................................................................................................74
6.3. Map Files....................................................................................................................................76
7. Utilities...................................................................................................................................................80
7.1. Archiver/Librarian....................................................................................................................... 80
7.2. Hexmate..................................................................................................................................... 81
Trademarks................................................................................................................................................ 217
1. Preface
Filenames autoexec.bat
Bit values 0, 1
Italic Courier New A variable argument file.o, where file can be any valid filename
2. Assembler Overview
The MPLAB XC8 PIC Assembler is a free-standing cross assembler and linker package, supporting all 8-bit PIC®
microcontrollers.
The internal assembler application used by the PIC Assembler is the same as that used by the MPLAB XC8 C
Compiler tool, with the assembly language being common between both tools. This document describes the use
of the PIC Assembler for writing and building source code written entirely in assembly. If you need assistance with
writing assembly code to be linked with C source code, or you are writing assembly code that is to be inserted in-line
with C code, refer to MPLAB® XC8 C Compiler User’s Guide for PIC® MCU (DS50002737) for information that is
better suited to these tasks.
3. Assembler Driver
The name of the command-line driver used by the MPLAB XC8 PIC Assembler is pic-as.
This driver can be invoked to perform both assembly and link steps and is the application called by development
environments, such as the MPLAB X IDE, to build assembly projects.
The pic-as driver has the following basic command format:
Throughout this manual, it is assumed that the assembler applications are in your console’s search path or that the
full path is specified when executing the application.
It is customary to declare options (identified by a leading dash “-” or double dash “--”) before the files’ names;
however, this is not mandatory.
The formats of the options are supplied in 3.4. Assembler Option Descriptions along with corresponding
descriptions of the options' function.
The files can be an assortment of assembler source files and precompiled intermediate files. While the order in
which these files are listed is not important, it can affect the allocation of code or data and can affect the names of
some of the output files.
The libraries is a list of user-defined library files that will be searched by the assembler. The order of these files
will determine the order in which they are searched. It is customary to insert the libraries after the list of source files;
however, this is not mandatory.
The driver will compile all source files, regardless of whether they have changed since the last build. Development
environments (such as MPLAB® X IDE) and make utilities must be employed to achieve incremental builds (see
3.2. Multi-step Assembly).
Unless otherwise specified, a HEX file and ELF file are produced as the final output. The intermediate files remain
after compilation has completed, but most other temporary files are deleted, unless you use the -save-temps
option (see 3.4.28. Save-temps Option) which preserves all generated files. Note that some generated files can be in
a different directory than your project source files (see also 3.4.27. O: Specify Output File).
The first two of the following command lines build an intermediate file for each assembly source file, then these
intermediate files are passed to the driver again to be linked in the last command.
As with any assembler, all the files that constitute the project must be present when performing the second (link)
stage of compilation.
You might also wish to generate intermediate files to construct your own library files. See 7.1. Archiver/Librarian for
more information on library creation.
After this file is saved, the compiler can be invoked with the following command:
pic-as @xyz.xc8
Command files can be used as a simple alternative to a make file and utility, and can conveniently store compiler
options and source file names. The MPLAB X IDE also allows such files to be used. The file name is specified in the
XC8 Linker > Additional options > Use response file to link field of the Project Properties.
Option Controls
(Links to explanatory section)
...........continued
Option Controls
(Links to explanatory section)
...........continued
Option Controls
(Links to explanatory section)
#ifdef MY_MACRO
movlw MY_MACRO;
#endif
the movlw instruction will be assembled and the value 1 will be assigned to the W register.
When the replacement, text, is specified with the option, the macro will subsequently expand to be the replacement
specified with the option. So if the above example code was compiled with the option -DMY_MACRO=0x55, then the
instruction would be assembled as: movlw 0x55
All instances of -D on the command line are processed before any -U options.
3.4.9 Help
The --help option displays information on the pic-as assembler options, then the driver will terminate.
Type Produces
none No call graph
crit Only critical paths in the callgraph
std Standard, short-form call graph (default)
full Full call graph
The callgraph is generated by the linker, primarily for the purposes of allocating memory to objects in the compiled
stack. Those routines defining stack objects that are not overlaid with other stack objects and that are hence
contributing to the program's data memory usage are considered as being on a critical path.
The start, end and destination attributes are, by default, hexadecimal constants. The addresses defining the
input range (start - end) are typically made multiples of the algorithm width. If this is not the case, bytes (with value
0) will pad any missing input word locations. The destination is where the hash result will be stored. This address
cannot be within the range of addresses over which the hash is calculated.
The following specifications are appended as a comma-separated list to this option.
Table 3-4. Checksum Arguments
Argument Description
width=n Optionally specifies the decimal width of the result. Results can be calculated for byte-widths of
1 to 4 bytes for most algorithms, but it represents the bit width for SHA algorithms. If a positive
width is requested, the result will be stored in big-endian byte order. A negative width will cause
the result to be stored in little-endian byte order. If the width is left unspecified, the result will be
2 bytes wide and stored in little-endian byte order. This width argument is not required with any
Fletcher algorithm, as they have fixed widths, but it may be used to alter the default endianism of
the result.
offset=nnnn Specifies an initial hexadecimal value or offset to be used in the hash calculation. It is not used
with SHA algorithms.
algorithm=n The decimal argument selects one of the hash algorithms implemented in Hexmate. The
selectable algorithms are described in Table 3-5. If unspecified, the default algorithm used is
8-bit checksum addition (algorithm 1).
polynomial=nn Selects the polynomial value when using CRC algorithms
...........continued
Argument Description
code=nn.Base Selects a hexadecimal code that will trail each byte in the result. This can allow each byte of
the hash result to be embedded within an instruction, for example code=34 will embed each
byte of the result in a retlw instruction on Mid-range devices, or code=0000 will append two
0x00 bytes to each byte of the hash. This code sequence can be optionally followed by .Base,
where Base is the number of bytes of the hash to be output before the trailing code sequence
is appended. A specification of code=1122.2, for example, will output the bytes 0x11 and 0x22
after each two bytes of the hash result.
revword=n Specifies a decimal word width. If this is non-zero, then bytes within each word are read in
reverse order when calculating a hash value. Words are aligned to the addresses in the HEX
file. At present, the width must be 0 or 2. A zero width disables the reverse-byte feature, as if
the revword suboption was not present. This suboption should be used when using Hexmate to
match a CRC produced by a PIC hardware CRC module that use the Scanner module to stream
data to it.
skip=n.Bytes Specifies a decimal word width. If this is non-zero, then the MSB within each word is skipped for
the purposes of calculating a hash value. Words are aligned to the addresses in the HEX file. At
present, the width must be 0 (which disables the skip feature, as if the skip suboption was not
present) or greater than 1. This value can be optionally followed by .Bytes, where Bytes is a
number representing the number of bytes to skip in each word, for example skip=4.2 will skip
the two most significant bytes in each 4-byte word.
Note that the reverse and skip features act on words that are aligned to the HEX file addresses, not to the position of
the data in the sequence being processed. In other words, the alignment of the words are not affected by the start
and end addresses specified with the option.
If an accompanying --fill option (3.4.5. Fill Option) has not been specified, unused locations within the specified
address range will be automatically filled with 0xFFF for baseline devices, 0x3FFF for mid-range devices, or 0xFFFF
for PIC18 devices. This is to remove any unknown values from the calculations and ensure the accuracy of the result.
For example:
-mchecksum=800-fff@20,width=1,algorithm=2
will calculate a 1-byte checksum from address 0x800 to 0xfff and store this at address 0x20. A 16-bit addition
algorithm will be used. Table 3-5 shows the available algorithms and 7.2.3. Hash Value Calculations describes these
in detail.
Table 3-5. Checksum Algorithm Selection
...........continued
Selector Algorithm description
7 Fletcher’s checksum (8 bit calculation, 2-byte result width)
8 Fletcher’s checksum (16 bit calculation, 4-byte result width)
10 SHA-2 (currently only SHA256 is supported)
The hash calculations are performed by the Hexmate application. The information in this driver option is passed to
the Hexmate application when it is executed.
family. You might use this option if your program does not fit in your intended target device and you wish to get an
indication of the code or data size reductions needed to be able to program that device.
The assembler will normally terminate if the selected device runs out of program memory, data memory, or EEPROM.
When using this option, the program memory of PIC18 and mid-range devices will be maximized to extend
from address 0 to either the bottom of external memory or the maximum address permitted by the PC register,
whichever is lower. The program memory of baseline parts is maximized from address 0 to the lower address of the
Configuration Words.
The number of data memory banks is expanded to the maximum number of selectable banks as defined by the BSR
register (for PIC18 devices), RP bits in the STATUS register (for mid-range devices), or the bank select bits in the
FSR register (for baseline devices). The amount of RAM in each additional bank is equal to the size of the largest
contiguous memory area within the physically implemented banks.
If present on the device, EEPROM is maximized to a size dictated by the number of bits in the EEADR or NVMADR
register, as appropriate.
If required, check the map file (see 6.3. Map Files) to see the size and arrangement of the memory available when
using this option with your device.
Note: When using the -mmaxichip option, you are not building for a real device. The generated code may not load
or execute in simulators or the selected device. This option will not allow you to fit extra code into a device.
3.4.20 Print-devices
The -mprint-devices option displays a list of devices the assembler supports.
The names listed are those devices that can be used with the -mcpu option. This option will only show those devices
that were officially supported when the assembler was released. Additional devices that might be available via device
family packs (DFPs) will not be shown in this list.
The assembler will terminate after the device list has been printed.
-mram=default,+100-1ff
This will add the range from 100h to 1ffh to the on-chip memory. To only use an external range and ignore any
on-chip memory, use:
-mram=0-ff
This option can also be used to reserve memory ranges already defined as on-chip memory in the relevant chipinfo
file. To do this, supply a range prefixed with a minus character, -, for example:
-mram=default,-100-103
will use all the defined on-chip memory, but not use the addresses in the range from 100h to 103h for allocation of
RAM objects.
This option will adjust the memory ranges used by linker classes (see 6.1.1. A: Define Linker Class Option) . Any
objects contained in a psect that do not use the classes affected by this option might be linked outside the valid
memory specified by this option.
-mreserve=space@start:end
where space can be either of ram or rom, denoting the data and program memory spaces, respectively; and start
and end are addresses, denoting the range to be excluded. For example, -mreserve=ram@0x100:0x101 will
reserve two bytes starting at address 100h from the data memory.
This option performs a similar task to the -mram and -mrom options, but it cannot be used to add additional memory
to that available for the program.
-mrom=default,+100-2ff
This will add the range from 100h to 2ffh to the on-chip memory. To only use an external range and ignore any
on-chip memory, use:
-mrom=100-2ff
This option can also be used to reserve memory ranges already defined as on-chip memory in the chip configuration
file. To do this supply a range prefixed with a minus character, -, for example:
-mrom=default,-100-1ff
will use all the defined on-chip memory, but not use the addresses in the range from 100h to 1ffh for allocation of
ROM objects.
This option will adjust the memory ranges used by linker classes (see 6.1.1. A: Define Linker Class Option) . Any
code or objects contained in a psect that do not use the classes affected by this option might be linked outside the
valid memory specified by this option.
Note that some psects must be linked above a threshold address, most notably some psects that hold const-
qualified data. Using this option to remove the upper memory ranges can make it impossible to place these psects.
A psect summary can be shown by enabling the psect type. This shows individual psects after they have been
grouped by the linker and the memory ranges they cover. Table 4-20 shows what summary types are available. The
default output printed corresponds to the mem setting.
SHA hashes for the generated hex file can also be shown using this option. These can be used to quickly determine
if anything in the hex file has changed from a previous build.
Table 3-6. Summary Types
Type Shows
psect A summary of psect names and the addresses where they were linked will be shown.
mem A concise summary of memory used will be shown (default).
class A summary of all classes in each memory space will be shown.
hex A summary of addresses and HEX files that make up the final output file will be shown.
file Summary information will be shown on screen and saved to a file.
sha1 A SHA1 hash for the hex file.
sha256 A SHA256 hash for the hex file.
xml Summary information will be shown on the screen, and usage information for the main memory spaces
will be saved in an XML file.
xmlfull Summary information will be shown on the screen, and usage information for all memory spaces will be
saved in an XML file.
If specified, the XML files contain information about memory spaces on the selected device, consisting of the space’s
name, addressable unit, size, amount used and amount free.
The -save-temps=obj form of this option is similar to -save-temps, but if the -o option is specified, the
temporary files are placed in the same directory as the output object file. If the -o option is not specified, the
-save-temps=obj switch behaves like –save-temps.
3.4.31 Version
The --version option prints assembler version information then exits.
Language Description
assembler Assembly source code
assembler-with-cpp Assembly source code that must be preprocessed
will tell the assembler to run the preprocessor over the assembly source file, even though the init.s file name does
not use a .S extension.
Instruction set This selector allows you to specify whether the Standard or Extended instruction set should be
used for projects targeting PIC18 devices. See 3.4.18. Isa Option.
Custom DFP path If you need to use an alternative Device Family Pack (DFP), enter the path to the DFP you wish
to use in this field. See 3.4.16. Dfp Option.
Summary The checkboxes in this dialog selects the type of information that is included in the summary that
selectors is displayed in the Output window once the build is complete. See 3.4.25. Summary Option option
for full details of each summary.
Verbose Selecting this checkbox will perform verbose compilation, showing the command lines
issued to the internal applications. See 3.4.30. V: Verbose Compilation.
Suppress all warnings Selecting this checkbox will prevent all warning messages from being issued. See
3.4.32. W: Disable all Warnings Option.
Maximum errors Use this field to specify the maximum number of errors that will be generated before the
assembler exits. See 3.4.6. Max Errors.
Warning level Use this field to specify the warning level threshold. Only warnings with higher levels will
be emitted during a build. See 3.4.26. Warn Option.
Define preprocessor Use this field to define preprocessor macros. See 3.4.2. D: Define a Macro.
symbol
Undefine preprocessor Use this field to undefine preprocessor macros. See 3.4.29. U: Undefine Macros.
symbol
Include directories Use this field to specify the directories searched for header files. See 3.4.10. I: Specify
Include File Search Path Option.
Assembler files with Select this checkbox to have assembly source files preprocessed before being passed
preprocessor to the assembler, regardless of the file extension. See 3.4.36. X: Specify Source
Language Option.
Custom assembler Use this field to have options not directly available in the project properties dialog passed
options to the assembler. See 3.4.33. Wa: Pass Option To The Assembler, Option.
Custom preprocessor Use this field to have options not directly available in the project properties dialog passed
options to the preprocessor. See 3.4.34. Wp: Pass Option To The Preprocessor Option.
Libraries Use this field to add the names of library archives. See 3.4.11. L: Specify Library File
Option.
Library search path Use this field to specify the paths to be searched for library archive files. See 3.4.12. L:
Specify Library Search Path Option.
Custom linker options Use this field to have options not directly available in the project properties dialog passed
to the linker. See 3.4.35. Wl: Pass Option To The Linker, Option.
Style of call graph Use this selector to choose what level of detail you require in the call graph printed in the
listing in map file map file. See 3.4.13. Callgraph Option.
Fill Use this field to specify the command to fill unused memory. See 3.4.5. Fill
Option.
Adjust program memory Use this field to adjust the program memory available on the device. See
ranges 3.4.23. Rom Option.
Adjust data memory ranges Use this field to adjust the data memory available on the device. See 3.4.21. Ram
Option.
Reserve memory range Use this field to reserve space in program and data memory. See 3.4.22. Reserve
Option.
Calculate and store a Use this field to specify a command to have a hash value calculated over the
checksum in program program output and stored in the HEX file. See 3.4.14. Checksum Option.
memory
Insert a hexadecimal code or Use this field to specify a command to have a code stored in the HEX file. See
serial number 3.4.24. Serial Option.
Build for a hypothetical Select this checkbox to build for a hypothetical device with the same physical core
maximized-resource device and peripherals as the selected device, but with the maximum allowable memory
resources permitted by the device family. See 3.4.19. Maxichip Option.
Map file generation Select this checkbox to have a map file generated by the linker. This will issue the
appropriate option to the linker using the driver's -Wl, option (see 3.4.35. Wl: Pass
Option To The Linker, Option).
Format hex file for This checkbox controls the special formatting of the final HEX file. See
download 3.4.17. Download Option.
Produce Intel Hex Select this checkbox to have an extended address Intel HEX file produced. See
extended address zero 3.4.7. G: Produce Debugging Information Option.
output
MPASM ,0 ,1
For example (ignoring bank selection and address masking for this example):
It is highly recommended that the destination operand is always specified with those instructions where it is needed.
If the destination operand is omitted, the destination is assumed to be the file register.
To specify the RAM access bit for PIC18 devices, you may use operands from either style shown in the table below.
Banked access indicates that the file register address specified in the instruction is just an offset into the currently
selected bank. Unbanked access indicates that the file register address is an offset into the Access bank, or common
memory.
Table 4-2. RAM Access Operand Styles
MPASM ,1 ,0
It is recommended that you always specify the RAM access operand or the common memory prefix. If these are
not present, the instruction address is absolute and the address is within the upper half of the access bank (which
dictates that the address must not masked), the instruction will use the access bank RAM. In all other situations, the
instruction will access banked memory.
If you use the XC8 style, the destination operand and the RAM access operand can be listed in any order for PIC18
instructions. For example, the following two instructions are identical:
addwf foo,f,c
addwf foo,c,f
Always be consistent in the use of operand style for each instruction, and preferably, that style should remain
consistent through the program. For example, the instruction addwf bar,1,c (which uses the MPASM-style ,1
destination suffix and the XC8-style ,c unbanked access suffix together in the same instruction) is illegal.
For example, the following instructions show the W register being moved to first, an absolute location; and then to
an address represented by an identifier. Bank selection and masking has been used in this example. The PIC18
opcodes for these instructions, assuming that the address assigned to foo is 0x516 and to bar is 0x55, are shown
below.
Notice that the first two instruction opcodes have the RAM access bit (bit 8 of the op-code) cleared, but that the bit is
set in the last two instructions.
Note: The manual masking of addresses used as instruction operands (for example using the BANKMASK()
or PAGEMASK() macros or ANDing the operand with a mask) is not necessary when using the -Wl,--
fixupoverflow option and any of the ignore, warn, or lstwarn arguments.
Note: The manual masking of addresses used as instruction operands (for example using the BANKMASK()
or PAGEMASK() macros or ANDing the operand with a mask) is not necessary when using the -Wl,--
fixupoverflow option and any of the ignore, warn, or lstwarn arguments.
In the same way, the PAGESEL() pseudo instruction can be used to generate code to select the page of the address
operand. For the current page, you can use the location counter, $, as the operand.
Depending on the target device, the generated code will either contain one or more instructions to set/clear bits in
the appropriate register, or use a movlp instruction in the case of enhanced mid-range PIC devices. As the directive
could expand to more than one instruction, it should not immediately follow a btfsx instruction. For example:
fcall _getInput
PAGESEL $ ;select this page
This directive is accepted when compiling for PIC18 targets but has no effect and does not generate any code.
Support is purely to allow easy migration across the 8-bit devices.
To manually mask a file register address (data memory), use the BANKMASK() macro. To manually mask a program
address used with the call and goto flow control instructions, use the PAGEMASK() macro. Both these macros
AND out the bank or page information in the address using a suitable device-specific mask. They are available once
you include <xc.inc> into a source module. Use of these macros (rather than manually using the AND operator, &)
increases code portability across Microchip devices, since they adjust the mask to suit the bank or page size of the
target device. The following code masks the addresses used by the subwf and call instructions:
BANKSEL flags ;select data bank of flags
subwf BANKMASK(flags) ;remove bank bits from address to prevent fixup overflow
PAGESEL myFunc ;select the page of myFunc
call PAGEMASK(myFunc) ;remove page bits from address to prevent fixup overflow
Rather than ANDing out the bank information in an address using either the BANKMASK() or PAGEMASK() macros,
the address can be XORed ( ^ operator) with a bitmask that represents the expected bank or page bits in the
address. If the address falls in the bank or page that was expected, then the upper bits of the bitmask and
address will XOR to zero; if this is not the case, the XOR will produce a non-zero component in the upper bits of
the address and trigger a fixup overflow error from the linker (assuming this error has not been disabled by the
-Wl,--fixupoverflow option).
The following example for a 16Fxxxx device (which has a data bank size of 0x80) selects bank 2 before accessing
the symbol flags. The flags symbol has been XORed with the mask 0x100, which represents the bitmap of bank 2
addresses with the address offset zeroed.
movlb 2 ;select bank 2
subwf flags^0x100
If flags was linked at address 0x153 (a bank 2 address), then 0x153^0x100 will result in the value 0x53, which fits
into the address field of the subwf instruction. If flags was accidentally linked to address 0x34 (a bank 0 address),
then 0x34^0x100 yields the result 0x134, which is too large to fit into the 7-bit wide address field of the subwf
instruction and which will trigger a fixup overflow error, alerting you to the problem.
Do not use the BANKMASK() or PAGESEL() macros with any instruction that expects its operand to be a full address,
such as the PIC18’s movff instruction for example.
Note that address masking is a fundamentally different operation to bank or page selection. Neither the -Wl,--
fixupoverflow option nor the BANKMASK() or PAGEMASK() macros select the bank or page of the object being
accessed, called, or jumped to. Regardless of how you handle address masking, you must always ensure that your
program contains the instructions to select the correct bank or page when required, as described in 4.1.2. Bank And
Page Selection. The one exception is when you use the fcall and/or ljmp pseudo instructions (see 4.1.7. Long
Jumps And Calls), which perform both page selection and address masking for you.
movfw foobar
movf foobar,w
The “0” and “1” operands indicated in the device data sheet can be alternatively used if desired.
The operand to the fcall and ljmp mnemonics should not be masked, regardless of target device. The full address
is required to determine the destination address and page (where applicable). When the mnemonic is expanded, the
address used with either the call or goto instruction in the expansion will be automatically masked. When using a
call or goto instruction directly in your source code, always apply the appropriate mask to the operand.
The following mid-range PIC example shows an fcall instruction in the assembly list file. You can see that the
fcall instruction has expanded to five instructions. In this example, there are two bit instructions that set/clear bits
in the PCLATH register. Bits are also set/cleared in this register after the call to reselect the page that was selected
before the fcall.
Since fcall and ljmp instructions can expand into more than one instruction, they should never be preceded by an
instruction that can skip, e.g., a btfsc instruction.
The fcall and ljmp instructions assume that the psect that contains them is smaller than a page. Do not use these
instructions to transfer control to a label in the current psect if it is larger than a page. The default linker options will
not permit code psects to be larger than a page.
On PIC18 devices, the regular call instruction can be followed by a “,f” to indicate that the W, STATUS and
BSR registers should be pushed to their respective shadow registers. This replaces the “,1” syntax indicated on the
device data sheet.
...........continued
Format # Field1 Field2 Field3 Field4
Format 2 label: mnemonic operands ; comment
4.3 Characters
The character set used is standard 7 bit ASCII. Alphabetic case is significant for identifiers, but not mnemonics and
reserved words. Tabs are equivalent to spaces.
4.3.1 Delimiters
All numbers and identifiers must be delimited by white space, non-alphanumeric characters or the end of a line.
4.4 Comments
An assembly comment is initiated with a semicolon that is not part of a string or character constant, for example:
movlw 22 ;this value will ensure there is a good safety margin
If the assembly file is first processed by the C preprocessor, then the file can also contain C or C++ style comments
using the standard /* ... */ and // syntax.
Avoid using assembly comments (;comment) in preprocessor directives, especially the #define directive.
Assembly comments are not removed by the C preprocessor prior to macro substitution and so will appear in the
substituted text, possibly resulting in build errors. Always use C or C++ style comments in these situations.
4.5 Constants
Radix Format
Binary Digits 0 and 1 followed by B.
Hexadecimal numbers must have a leading digit (e.g., 0ffffh) to differentiate them from identifiers. Hexadecimal
digits are accepted in either upper or lower case.
4.6 Identifiers
Assembly identifiers are user-defined symbols representing memory locations or numbers. A symbol can contain any
number of characters drawn from alphabetics, numerics, as well as special characters: dollar, $; question mark, ?;
and underscore, _.
The first character of an identifier cannot be numeric nor the $ character. The case of alphabetics is significant, e.g.,
Fred is not the same symbol as fred. Some examples of identifiers are shown here:
An_identifier
an_identifier
an_identifier1
?$_12345
An identifier cannot have the same symbol (any case) as any of the assembly code mnemonics (e.g. movlw or
return) assembler directives (e.g. SET or LIST), directive argument tokens (e.g. hex or push), or operators (e.g.
mod or nul).
will represent code that will jump to itself and form an endless loop. By using this symbol and an offset, a relative
jump destination can be specified.
Any address offset added to $ has the native addressability of the target device. So, for baseline and mid-range
devices, the offset is the number of instructions away from the current location, as these devices have word-
addressable program memory. For PIC18 instructions, which use byte addressable program memory, the offset to
this symbol represents the number of bytes from the current location. As PIC18 instructions must be word aligned,
the offset to the location counter should be a multiple of 2. All offsets are rounded down to the nearest multiple of 2.
For example:
will skip the movlw instruction on baseline or mid-range devices. On PIC18 devices, goto $+2 will jump to the
following instruction; i.e., act like a nop instruction.
Preproccessor macros are also defined for fields (often bits) within each register. These macros expand to be the
address of the enclosing register followed by a comma and then the bit offset of that field within the register. This
makes the symbol directly usable inside bit-orientated instructions, like bsf or btfsc etc. For example, bit #5 inside
the PORTB register can be accessed using the symbol RB5. For example:
btfss RB5
incf count
Some devices have the same SFR field name used in more than one register. In these cases, no symbol will be
defined for any of these fields. To access these fields, you must use the SFR name and a pre-defined macro that
represent the field's bit position in the register. If required, this method of accessing fields within SFRs can be used
with any field in any register. For example, some devices define more than one IPEN bit and so you would need to
access IPEN with code similar to:
bsf BANKMASK(INTCON0),INTCON0_IPEN_POSN,c ;set the IPEN bit in the INTCON0
register
Symbols are also not defined when the field name is a single letter, for example the carry bit in the STATUS register
is called C, but there will be no symbol with this name defined. In some cases, there might be an alternate name
provided, for example CARRY, but the field can always be access in a manner similar to that shown in the above
example.
Note: The manual masking of addresses used as instruction operands (for example using the BANKMASK()
or PAGEMASK() macros or ANDing the operand with a mask) is not necessary when using the -Wl,--
fixupoverflow option and any of the ignore, warn, or lstwarn arguments.
The <xc.inc> header supplies a complete set of field-position equates representing the field's bit position in
its register, size (in bits), and a bitmask that can be used to perform bitwise operations on the field. These
equates have the form REGISTERNAME_FIELDNAME_SUFFIX, where SUFFIX can be POSITION or its alias
POSN, SIZE or its alias LENGTH, or MASK. For example, the following are defined for the RA3 field in the
PSECT myCode,class=CODE,delta=2
start:
movlw 1
goto fin
more: clrf _input
return
PSECT myDATA,class=BANK1,space=1
myVar:
DS 2 ;2 bytes of storage, please
Here, the label start will ultimately be assigned the same address as the movlw instruction, and more, the same
address as the clrf instruction. The label myVar will be assigned same address as the start address of the block of
memory reserved by the DS directive.
Labels can be used (and are preferred) in assembly code, rather than using an absolute address with other
instructions. In this way, they can be used as the target location for jump-type instructions or to load an program
or data memory address into a register.
Like C variables, assembly labels have scope. By default, they can be used anywhere in the module in which they
are defined. They can be used by code located in the source file before their definition. To make a label accessible in
other modules, use the GLOBAL directive (see 4.9.29. Global Directive for more information).
The assembler will not output information relating to labels that do not use the GLOBAL directive, thus you will not see
any such symbols appear in the map or symbol files, for example.
...........continued
Operator Purpose Example
/ division movlw 100/4
= or eq equality IF inp eq 66
If you create your own psects, try to associate them with an existing linker class (see 5.3. Default Linker Classes and
6.1.2. C: Associate Linker Class To Psect) otherwise you can need to specify linker options for them to be allocated
correctly.
Note, that the length and placement of psects is important. It is easier to write code if all executable code is located
in psects that do not cross any device pages boundaries; so, too, if data psects do not cross bank boundaries. The
location of psects (where they are linked) must match the assembly code that accesses the psect contents.
Directive Purpose
ALIGN Aligns output to the specified boundary.
BANKISEL Generates code to select bank of operand for indirect access on some devices.
DS Reserves storage.
FILE Indicates the source file that contains the assembly code following.
FNADDR Indicates a routine's address has been taken.
...........continued
Directive Purpose
FNARG Indicates calls in a routine's arguments.
FNBREAK Breaks links in the call graph.
FNCALL Indicates call hierarchy.
FNCONF Indicates call stack settings.
FNINDIR Indicates indirect calls made by routines.
FNSIZE Indicates the size of a routines auto and parameter objects.
FNROOT Indicates the root of a call tree.
GLOBAL Makes symbols accessible to other modules or allow reference to other global symbols defined in
other modules.
IF Conditional assembly.
LINE Indicates the line number of the current source file that contains the assembly code following.
PAGESEL Generates set/clear instruction to set PCLATH bits for this page.
PROCESSOR Defines the particular chip for which this file is to be assembled.
PUBLIC Makes non-EXTRN symbols accessible to other modules or allow reference to other global
symbols defined in other modules.
RADIX Specifies radix for numerical constants.
SUBTITLE Specifies the subtitle of the program for the listing file.
TITLE Specifies the title of the program for the listing file.
...........continued
Directive Purpose
WARN Generates a user-defined warning.
ALIGN 2
Note that what follows will only begin on an even absolute address if the psect begins on an even address; i.e.,
alignment is done within the current psect. See 4.9.47.16. Reloc Flag for psect alignment.
The ALIGN directive can also be used to ensure that a psect’s length is a multiple of a certain number. For example,
if the above ALIGN directive was placed at the end of a psect, the psect would have a length that was always an
even number of bytes long.
Action Purpose
off Disables the assembler optimizer for subsequent code.
on Enables the assembler optimizer for subsequent code.
pop Retrieves the state of the assembler optimization setting.
push Saves the state of the assembler optimization setting.
No code is modified after an ASMOPT off directive. Following an ASMOPT on directive, the assembler will perform
allowable optimizations.
The ASMOPT push and ASMOPT pop directives allow the state of the assembler optimizer to be saved onto a stack
of states and then restored at a later time. They are useful when you need to ensure the optimizers are disabled for a
small section of code, but you do not know if the optimizers have previously been disabled.
For example:
ASMOPT PUSH ;store the state of the assembler optimizers
ASMOPT OFF ;optimizations must be off for this sequence
movlw 0x55
movwf EECON2
movlw 0xAA
movwf EECON2
ASMOPT POP ;restore state of the optimizers
Note that no optimizations are performed by the MPLAB XC8 PIC Assembler and these controls will be ignored.
#include <xc.inc>
PSECT udata_bank1
myVar:
DS 1
PSECT code
setMode:
movlw myVar
movwf FSR ;Load the address of myVar info FSR
BANKISEL myVar ;Select the correct bank for myVar
movlw 055h
movwf INDF ;Indirectly write to myVar
This directive will set the IRP bit (Mid-range) or STATUS bits (Baseline) appropriately for the symbol argument. For all
other devices, this directive will be ignored.
Here, setting is a configuration setting descriptor (e.g., WDT) and value can be either a textual description
of the desired state (e.g., OFF) or a numerical value. Either the setting or value tokens or the setting =
value expression can be surrounded by either double or single quotes to protect them from any macro substitution
performed by the preprocessor, for example:
CONFIG "WDT = ON" ;turn on watchdog timer
CONFIG "FEXTOSC" = "ECH" ;external clock oscillator mode, high power PFM
CONFIG WDTPS = 0x1A ;specify the timer postscale value
Some value tokens that appear to be purely numerical are in fact a textual description of the value, for example in
the following:
config WDTPS = 32
the 32 token is a textual description for some devices that indicates a watchdog timer post-scale of 1:32, not
the number 32. In such a case, it might not be the number 32 that is programmed into the relevant bits of the
configuration register. The assembler will first check if value represents a predefined string and, only if that is not
the case, assume it represents a numerical constant, which will then be subject to the same constraints as other
numerical constant operands.
You should never assume that the OFF and ON tokens used in configuration macros equate to 0 and 1, respectively,
as that is often not the case.
The register field is the name of a configuration or id-location register, and this must always be used with a value
that is a numerical constant, for example:
CONFIG CONFIG1L = 0x8F
The available setting, register and value fields are documented in the chipinfo file relevant to your device (i.e.
pic_chipinfo.html and pic18_chipinfo.html) and that are located in the docs directory of your compiler
installation. Click the link to your target device and the page will show you the settings and values that are
appropriate with this pragma. Review your device data sheet for more information.
One CONFIG directive can be used to set each configuration setting; alternatively, several comma-separated
configuration settings can be specified by the same directive. The directive can be used as many times as required to
fully configure the device.
The following example shows a configuration register being programmed as a whole and programmed using the
individual settings contained within that register.
; PIC18F67K22
; VREG Sleep Enable bit : Enabled
; LF-INTOSC Low-power Enable bit : LF-INTOSC in High-power mode during Sleep
; SOSC Power Selection and mode Configuration bits : High Power SOSC circuit
selected
; Extended Instruction Set : Enabled
CONFIG RETEN = ON, INTOSCSEL = HIGH, SOSCSEL = HIGH, XINST = ON
; Alternatively
CONFIG CONFIG1L = 0x5D
; IDLOC @ 0x200000
CONFIG IDLOC0 = 0x15
All the bits in the Configuration Words should be programmed to prevent erratic program behavior. Do not leave them
in their default/unprogrammed state. Not all Configuration bits have a default state of logic high; some have a logic
low default state. Consult your device data sheet for more information.
If you are using MPLAB X IDE, take advantage of its built-in tools to generate the required pragmas, so that you can
copy and paste them into your source code. See the MPLAB® X IDE User’s Guide for a description and use of the
Configuration Bits window.
where memorySpace is a number representing the memory space in which the reservation will take place, address
is the address at which the reservation will take place and bytes is the number of bytes that is to be reserved. The
symbol is optional and refers to the name of the object at the address.
Specifying a symbol allows you to access the reserved memory in your code. This symbol is automatically made
globally accessible and is equated to the address specified in the directive. For example, the symbol, foo, defined by
the following directive:
DABS 1,0x100,4,foo
Note: The manual masking of addresses used as instruction operands (for example using the BANKMASK()
or PAGEMASK() macros or ANDing the operand with a mask) is not necessary when using the -Wl,--
fixupoverflow option and any of the ignore, warn, or lstwarn arguments.
This directive differs to the DS directive in that it can be used to reserve memory at any location, not just within the
current psect. Indeed, these directives can be placed anywhere in the assembly code and do not contribute to the
currently selected psect in any way. Additionally, objects defined by the DS directive inside a psect are allocated free
memory by the linker, whereas the allocation address must be specified and manged by the programmer when using
the DABS directive.
The memory space number is the same as the number specified with the space flag option to psects (see
4.9.47.18. Space Flag).
The linker reads this DABS-related information from object files and ensures that the reserved addresses are not used
for other memory placement.
4.9.9 Db Directive
The DB directive is used to initialize bytes of program memory.
The directive takes a comma-separated list of arguments. Each argument can be a numeric value (e.g., 55), a
character constant (e.g. 'T'), or a string (e.g. "level" or 'level'). Each argument or each character of a string
argument is written as one byte into consecutive program memory locations within the current psect.
The encoding of the values written depend on the delta flag of the psect that contains the directive. In the following
code:
PSECT myBytes,class=CODE,delta=2
alabel:
DB ’X’,1,2,3,4,
the size of the address unit in the program memory specified by the delta psect flag (see 4.9.47.4. Delta Flag) is 2
bytes (true for Baseline and Mid-range PIC devices). In this case, the DB directive will initialize each word of program
memory with the upper byte set to zero, specifically (in hexadecimal):
However, on PIC18 devices, which uses program memory psects with the delta flag set to 1, no padding will occur.
For the code:
PSECT myBytes,class=CODE,delta=1
alabel:
DB 'X',1,2,3,4
the following (hexadecimal) data will be defined in the HEX file for the program memory.
58 01 02 03 04
Strings consist of a sequence of characters enclosed within either single or double quotes. There is no termination
character added by the assembler. If you need a nul-terminated string, then specify the termination character as a
separate argument to the DB directive, for example:
PSECT myConst,class=CODE,delta=1
bytes:
DB "a terminated string",0
will define:
61 20 74 65 72 6D 69 6E 61 74 65 64 20 73 74 72 69 6E 67 00
The DB directive cannot be used to created objects in data memory. For that, use the DS directive (see 4.9.13. Ds
Directive).
PSECT myWords,class=CODE,delta=2
alabel:
DDW 'X',1,2,398,0x8005FFFF
the DDW directive will initialize each word of program memory with the supplied value, specifically (in hexadecimal):
Strings consist of a sequence of characters enclosed within either single or double quotes. There is no termination
character added by the assembler. If you need a nul-terminated string, then specify the termination character as a
separate argument to the DDW directive, for example:
PSECT myConst,class=CODE,delta=1
words:
DDW "a terminated string",0
will define:
00000061 00000020 00000074 00000065 00000072 0000006D 00000069 0000006E 00000061
00000074
00000065 00000064 00000020 00000073 00000074 00000072 00000069 0000006E 00000067
00000000
The DDW directive cannot be used to created objects in data memory. For that, use the DS directive (see 4.9.13. Ds
Directive).
Action Purpose
C Favor debugging C source.
asm Favor debugging assembly source.
pop Retrieves the state of the assembler debug source
setting.
push Saves the state of the assembler debug source setting.
This directive controls the generation of information that might affect debugging, for example the debug information
associated with labels, which can restrict the full expansion of assembly macros shown in the MPLAB X IDE
Disassembly View. The directive only affects how the code is debugged; it does not affect the operation of assembled
code.
If this directive is not specified, the asm setting is employed. Use this setting for projects built with the PIC Assembler
or around assembly code using macros that is part of a C project. The c setting will automatically be used in
assembly output from the MPLAB XC8 C compiler for assembly generated from, C code.
The DEBUG_SOURCE push and DEBUG_SOURCE pop directives allow the state of the debug source setting to be
saved onto a stack of states and then restored at a later time. They are useful when you need to set a particular
debug source state for a small section of code, but you do not know what state the debug source setting had
previously been.
For example:
DEBUG_SOURCE push ;store the state of the debug source setting
DEBUG_SOURCE asm ;ensure proper debugging of the macro used below
MY_UNLOCK_MACRO ;this should expand in the Disassembly View
DEBUG_SOURCE pop ;restore state of the debug source setting
The memorySpace argument is a number representing the linear memory space. This will be the same number as
the banked data space. The address is the address at which the reservation will take place. This can be specified
as either a linear or banked address. The bytes is the number of bytes that is to be reserved. The symbol is optional
and refers to the name of the object at the address.
Specifying a symbol allows you to access the reserved memory in your code. The symbol is automatically made
globally accessible and is equated to the address specified in the directive in linear addressing form. For example,
the symbol, foo, defined by the following directive:
DLABS 1,0x120,128,foo
will be assigned the linear address 0x20A0 and can be used in code, for example:
movlw low(foo)
movwf FSR1L
movlw high(foo)
movwf FSR1H
The memory space number is the same as the number specified with the space flag option to psects (see
4.9.47.18. Space Flag).
The linker reads this DLABS-related information from object files and ensures that the reserved addresses are not
used for other memory placement.
4.9.13 Ds Directive
The DS units directive reserves, but does not initialize, the specified amount of space. The single argument is the
number of address units to be reserved. An address unit is determined by the flags used with the psect that holds the
directive.
This directive is typically used to reserve bytes for RAM-based objects in the data memory (the enclosing psect's
space flag set to 1). If the psect in which the directive resides is a bit psect (the psect's bit flag was set), the
directive reserves the request number of bits. If used in a psect linked into the program memory, it will move the
location counter, but not place anything in the HEX file output. Note that on Mid-range and Baseline devices, the size
of an address unit in the program memory is 2 bytes (see 4.9.47.4. Delta Flag), so the DS pseudo-op will actually
reserve words in that instance.
An object is typically defined by using a label and then the DS directive to reserve locations at the label location.
Examples:
PSECT myVars,space=1,class=BANK2
alabel:
DS 23 ;reserve 23 bytes of memory
PSECT myBits,space=1,bit,class=COMRAM
xlabel:
DS 2+3 ;reserve 5 bits of memory
4.9.14 Dw Directive
The DW directive is used to initialize 16-bit words of program memory.
The directive takes a comma-separated list of arguments. Each argument can be a numeric value (e.g., 55), a
character constant (e.g. 'T'), or a string (e.g. "level" or 'level'). Each argument or each character of a string
argument is written as two bytes into consecutive program memory locations within the current psect.
In the following code:
PSECT myWords,class=CODE,delta=2
alabel:
DW 'X',1,2,398,5472
the DW directive will initialize each word of program memory with the supplied value, specifically (in hexadecimal):
Strings consist of a sequence of characters enclosed within either single or double quotes. There is no termination
character added by the assembler. If you need a nul-terminated string, then specify the termination character as a
separate argument to the DW directive, for example:
PSECT myConst,class=CODE,delta=1
words:
DW "a terminated string",0
will define:
0061 0020 0074 0065 0072 006D 0069 006E 0061 0074 0065 0064 0020 0073 0074 0072
0069 006E 0067 0000
The DW directive cannot be used to created objects in data memory. For that, use the DS directive (see 4.9.13. Ds
Directive).
or
The identifier thomas will be given the value 123h. EQU is legal only when the symbol has not previously been
defined. See 4.9.51. Set Directive for redefinition of values.
This directive does not reserve memory for the symbol specified. Use the DS directive to reserve data memory
(see 4.9.13. Ds Directive). An EQU performs a similar function to the preprocessor’s #define directive (see
5.1. Preprocessor Directives).
This directive is used to build debug information associated with a project and it is typically found in intermediate
assembly files, placed there by the C code generator. They shouldn't be required for hand-written assembly code.
FNCONF rbss,?a,?
tells the linker that the compiled stack should be placed in a psect called rbss, and that any auto variable block start
with the string ?a and function argument blocks start with ?. Thus, a routine called foo which defines compiled stack
objects using an FNARG directive would create two blocks started by the identifiers ?afoo and ?foo in the psect
called rbss.
FNINDIR _fred,8249
indicates that the routine fred needs 10 bytes of auto variables and 5 bytes of arguments. See 4.9.25. Fnconf
Directive for information how to access these areas of memory.
directive must be used at least twice: once in the module that defines the symbol to make that symbol public and
again in the module that uses the symbol to link in with the external definition.
For example:
GLOBAL lab1,lab2,lab3
IF ABC
goto aardvark
ELSIF DEF
goto denver
ELSE
goto grapes
ENDIF
ENDIF
In this example, if ABC is non-zero, the first goto instruction will be assembled but not the second or third. If ABC is
zero and DEF is non-zero, the second goto instruction will be assembled but the first and third will not. If both ABC
and DEF are zero, the third goto instruction will be assembled.
INCLUDE "options.inc"
The assembler driver does not pass any search paths to the assembler, so if the include file is not located in the
current working directory, the file's full path must be specified with the file name.
Assembly source files with a .S extension are preprocessed, thus allowing use of preprocessor directives, such as
#include, which is an alternative to the INCLUDE directive.
IRP number,4865h,6C6Ch,6F00h
DW number
ENDM
DW 4865h
DW 6C6Ch
DW 6F00h
Note that you can use local labels and angle brackets in the same manner as with conventional macros.
The IRPC directive is similar, except it substitutes one character at a time from a string of non-space characters.
For example:
IRPC char,ABC
DB ’char’
ENDM
DB ’A’
DB ’B’
DB ’C’
This directive is used to build debug information associated with a project and it is typically found in intermediate
assembly files, placed there by the C code generator. They shouldn't be required for hand-written assembly code.
when expanded, will include a unique assembler generated label in place of more. For example:
down foobar
expands to:
If invoked a second time, the label more would expand to ??0002 and multiply defined symbol errors will be averted.
When used, this macro will expand to the 2 instructions in the body of the macro, with the formal parameters
substituted by the arguments. Thus:
movlf 2,tempvar
expands to:
movlw 2
movwf tempvar mod 080h
The & character can be used to permit the concatenation of macro arguments with other text, but is removed in the
actual expansion. For example:
will load PORTA if port is A when called, etc. The special meaning of the & token in macros implies that you can not
use the bitwise AND operator, (also represented by &), in assembly macros; use the and form of this operator instead.
A comment can be suppressed within the expansion of a macro (thus saving space in the macro storage) by opening
the comment with a double semicolon, ;;.
When invoking a macro, the argument list must be comma-separated. If it is desired to include a comma (or other
delimiter such as a space) in an argument then angle brackets < and > can be used to quote
If an argument is preceded by a percent sign, %, that argument will be evaluated as an expression and passed as a
decimal number, rather than as a string. This is useful if evaluation of the argument inside the macro body would yield
a different result.
The nul operator can be used within a macro to test a macro argument, for example:
See 4.9.35. Local Directive for use of unique local labels within macros.
By default, the assembly list file will show macro in an unexpanded format; i.e., as the macro was invoked. Expansion
of the macro in the listing file can be shown by using the EXPAND assembler directive (see 4.9.18. Expand Directive).
IF MODE
call process
ELSE
MESSG "no mode defined"
ENDIF
4.9.38 Nocond
Using the NOCOND directive will prevent conditional code from being included in the assembly list file output. See also
the COND directive in 4.9.6. Cond Directive.
ORG 100h
will move the location counter to the beginning of the current psect plus 100h. The actual location will not be known
until link time.
In order to use the ORG directive to set the location counter to an absolute value, the directive must be used from
within an absolute, overlaid psect. For example:
PSECT absdata,abs,ovrld
ORG 50h
;this is guaranteed to reside at address 50h
PROCESSOR 18F4520
Flag Meaning
abs psect is absolute.
bit psect holds bit objects.
class=name Specify class name for psect.
delta=size Size of an addressing unit.
global psect is global (default).
inline psect contents (function) can be inlined when called.
...........continued
Flag Meaning
keep psect will not be deleted after inlining.
limit=address Upper address limit of psect (PIC18 only).
local psect is unique and will not link with others having the same name.
lowdata psect will be entirely located below the 0x1000 address.
merge=allow Allow or prevent merging of this psect.
noexec For debugging purposes, this psect contains no executable code.
note psect does not contain any data that should appear in the program image.
optim=optimizations specify optimizations allowable with this psect.
ovrld psect will overlap same psect in other modules.
pure psect is to be read-only.
reloc=boundary Start psect on specified boundary.
size=max Maximum size of psect.
space=area Represents area in which psect will reside.
split=allow Allow or prevent splitting of this psect.
with=psect Place psect in the same page as specified psect.
Class names are also useful where psects need only be positioned anywhere within a range of addresses rather than
at a specific address. The association of a class with a psect that you have defined typically means that you do not
need to supply a custom linker option to place it in memory.
See 6.1.1. A: Define Linker Class Option for information on how linker classes are defined.
Name Optimization
inline Allow the psect content to be inlined.
jump Perform jump-based optimizations.
merge Allow the psect’s content to be merged with that of other similar psects (PIC10/12/16 devices only).
pa Perform proceedural abstraction.
peep Perform peephole optimizations.
remove Allow the psect to be removed entirely if it is completely inlined.
split Allow the psect to be split into smaller psects if it surpasses size restrictions (PIC10/12/16 devices only).
empty Perform no optimization on this psect.
PSECT myText,class=CODE,reloc=2,optim=inline:jump:split
allows the assembler optimizer to perform inlining, splitting and jump-type optimizations of the myText psect content
if those optimizations are enabled. The definition:
PSECT myText,class=CODE,reloc=2,optim=
disables all optimizations associated with this psect regardless of the optimizer setting.
The optim psect flag replaces the use of the separate psect flags: merge, split, inline and keep.
Devices that have a banked data space do not use different space values to identify each bank. A full address that
includes the bank number is used for objects in this space. So, each location can be uniquely identified. For example,
a device with a bank size of 0x80 bytes will use address 0 to 0x7F to represent objects in bank 0, and then addresses
0x80 to 0xFF to represent objects in bank 1, etc.
For example:
PUBLIC lab1,lab2,lab3
Radix Meaning
dec Decimal constants
hex Hexadecimal constants
oct Octal constants
REPT 3
addwf fred,w
ENDM
addwf fred,w
addwf fred,w
addwf fred,w
thomas SET 0h
This directive does not reserve memory for the symbol specified. Use the DS directive to reserve data memory
(see 4.9.13. Ds Directive). A SET performs a similar function to the preprocessor’s #define directive (see
5.1. Preprocessor Directives).
SIGNAT _fred,8192
associates the signature value 8192 with the symbol _fred. If a different signature value for _fred is present in any
object file, the linker will report an error.
Often, this directive is used with assembly language routines that are called from C. The easiest way to determine
the signature value used by the MPLAB XC8 C Compiler is to write a C routine with the same prototype as that
required for the assembly routine, and check that function's signature directive argument, as determined by the code
generator and as shown in the assembly list file.
IF MODE
movwf modeQ
ELSE
WARN "MODE is zero - write skipped"
ENDIF
5. Assembler Features
The PIC Assembler provided access to a C preprocessor and many predefined psects and identifiers that you can
use in your programs.
#line Specify line number and filename for listing #line 3 final
#nn filename (where nn is a number, and filename is the name of #20 init.c
the source file) the following content originated from the
specified file and line number.
#undef Undefines preprocessor symbol. #undef FLAG
#warning Generate a warning message. #warning Length not set
Macro expansion using arguments can use the # character to convert an argument to a string and the ## sequence
to concatenate arguments. If two expressions are being concatenated, consider using two macros in case either
expression requires substitution itself; for example
lets you use the paste macro to concatenate two expressions that themselves can require further expansion.
Remember, that once a macro identifier has been expanded, it will not be expanded again if it appears after
concatenation.
The linker class associated with each of these psects and the device families for which they are defined are indicated
in the table. The linker classes shown are also already predefined by the PIC Assembler, so you do not need to
define them.
You can instead use psects and linker classes that you define, if required. In situations where a psect must reside at
a specific location, you must use a unique psect so that it can be linked independently to others. See 4.9.47. Psect
Directive and 6.1.19. P: Position Psect.
Table 5-2. Assembler-provided Psects and Linker Classes
Classes are defined by linker options (see 6.1.1. A: Define Linker Class Option). The assembler driver passes a
default set of such options to the linker, based on the selected target device. The names of linker classes are case
sensitive.
Psects are typically allocated free memory from the class they are associated with. The association is made using the
class flag with the PSECT directive (see 4.9.47.3. Class Flag). Alternatively, a psect can be explicitly placed into the
memory associated with a class using a linker option (see 6.1.19. P: Position Psect).
Classes can represent a single memory range, or multiple ranges. Even if two ranges are contiguous, the address
where one range ends and the other begins, forms a boundary, and psects placed in the class can never cross such
boundaries. You can create classes that cover the same addresses, but which are divided into different ranges and
have different boundaries. This allows you to accommodate psects whose contents makes assumptions about where
it or the data it accesses would be located in memory. Memory allocated from one class will also be reserved from
other classes that specify the same memory addresses.
To the linker, there is no significance to a class name or the memory it defines.
Memory can be removed from these classes if using the -mreserve option (see 3.4.22. Reserve Option), or when
subtracting memory ranges using the -mram and -mrom options (see 3.4.21. Ram Option and 3.4.23. Rom Option).
Other than reserve memory from classes, never change or remove address boundaries specified by a class.
CODE Consists of ranges that map to the program memory pages on the target device and are used for psects
containing executable code.
On Baseline devices, it can only be used by code that is accessed via a jump table.
ENTRY Is relevant for Baseline device psects containing executable code that is accessed via a call
instruction. Calls can only be to the first half of a page on these devices.
The class is defined in such a way that it spans a full page, but the psects it holds will be positioned so
that they start in the first half of the page.
This class is also used in Mid-range devices and will consist of many 0x100 word-long ranges, aligned
on a 0x100 boundary.
STRING Consists of ranges that are 0x100 words long and aligned on a 0x100 boundary. Thus, it is useful for
psects whose contents cannot span a 0x100 word boundary.
STRCODE Defines a single memory range that covers the entire program memory. It is useful for psects whose
content can appear in any page and can cross page boundaries.
CONST Consists of ranges that are 0x100 words long and aligned on a 0x100 boundary. Thus, it is useful for
psects whose contents cannot span a 0x100 word boundary.
RAM Consists of ranges that cover all the general purpose RAM memory of the target device, but excluding any
common (unbanked) memory.
Thus, it is useful for psects that must be placed within any general-purpose RAM bank.
BIGRAM Consists of a single memory range that is designed to cover the linear data memory of Enhanced
Mid-range devices, or the entire available memory space of PIC18 devices.
It is suitable for any psect whose contents are accessed using linear addressing or which does not need
to be contained in a single data bank.
ABS1 Consists of ranges that cover all the general purpose RAM memory of the target device, including any
common (unbanked) memory.
Thus, it is useful for psects that must be placed in general purpose RAM, but can be placed in any bank or
the common memory,
BANKx (where x is a bank number) — each consist of a single range that covers the general purpose RAM in that
bank, but excluding any common (unbanked) memory.
COMMON Consists of a single memory range that covers the common (unbanked) RAM, if present, for all Mid-range
devices.
COMRAM Consists of a single memory range that covers the common (unbanked) RAM, if present, for all PIC18
devices.
SFRx (where x is a number) — each consists of a single range that covers the SFR memory in bank x.
These classes would not typically be used by programmers as they do not represent general purpose
RAM.
CONFIG Consists of a single range that covers the memory reserved for configuration bit data.
This class would not typically be used by programmers as it does not represent general purpose RAM.
IDLOC Consists of a single range that covers the memory reserved for ID location data in the hex file.
This class would not typically be used by programmers as it does not represent general purpose RAM.
EEDATA Consists of a single range that covers the EEPROM memory of the target device, if present.
This class is used for psects that contain data that is to be programmed into the EEPROM.
The FNCONF directive (see 4.9.25. Fnconf Directive) should be used once per program. It's three arguments indicate
to the linker the name of the psect that should be used to hold the compiled stack, the symbol prefix to be used for
auto-style objects, and the symbol prefix to be used for parameter objects.
The FNROOT directive (see 4.9.27. Fnroot Directive) should be used once for each routine that forms the root node
in a callgraph. The memory allocated to stack objects can be overlapped with that of other routines within the same
callgraph, but no overlapping will take place between the stack objects of routines that are in different callgraphs.
Typically you will define one callgraph root for the main part of your program and then one for each interrupt routine.
This way, the stack memory associated with interrupt routines is kept separate and no data corruption can occur.
The FNSIZE directive (see 4.9.28. Fnsize Directive) should be specified for each routine that needs to have objects
plaed on the compiled stack. It takes three arguments, those being the name of a routine, the total number of bytes
required for that routine's auto-like objects, and the total number of bytes for its parameter-like objects. The directive
can be placed anywhere in your code, but it is often located near the routine it configures.
The FNCALL directive (see 4.9.24. Fncall Directive) is used as many times as required to indicate which routines
(that use the compiled stack) are called and from where. From this information, the linker can form the callgraph. As
you develop your program, you will need to ensure that there is an FNCALL directive for each unique call that takes
place in your code. If a called routine does not define any compiled stack objects, the directive is not required for that
routine, but it is good practice to include it anyway, in case there are subsequent changes made to the program.
The linker will create the special symbols to be used for auto-like and parameter objects for all routines that used the
FNSIZE directive. The following example of a cut-down program shows the stack being set up, with the main and add
routines requesting that they each require space on the stack. The main routines reads the special symbols created
by the linker for its auto-like objects; the add routine uses special symbols for its parameters..
FNCONF udata_acs,?au_,?pa_ ;setup the stack
FNROOT main ;the main routine is a callgraph root
PSECT code
FNSIZE main,4,0 ;the main routine needs 4 bytes of auto-like
objects
GLOBAL ?au_main ;make the symbol created by the linker globally
accessible
main:
...
loop:
movff ?au_main+0,?pa_add+0 ;load the first byte of the first parameter
movff ?au_main+1,?pa_add+1 ;load the second byte of the first parameter
movff ?au_main+2,?pa_add+2 ;load the first byte of the second parameter
movff ?au_main+3,?pa_add+3 ;load the second byte of the second parameter
FNCALL main,add ;the main routine will call the add routine in
the callgraph
call add ;the actual call
...
Provided that the link stage has successfully concluded, the listing file is updated by the linker so that it contains
absolute addresses and symbol values. Thus, you can use the assembler list file to determine the position and exact
opcodes of instructions. Tick marks “'” in the assembly listing, next to addresses or opcodes, indicate that the linker
did not update the list file, most likely due to a build error, or a assembler option that stopped compilation before the
link stage. For example, in the following listing:
These marks indicate that addresses are just address offsets into their enclosing psect, and that opcodes have not
been fixed up. Any address field in the opcode that has not been fixed up is shown with a value of 0.
• Only symbols associated with the assembly module, from which the list file is produced (as opposed to the
entire program) are listed.
• Local as well as global symbols associated with that module are listed.
Each symbol is listed along with the address it has been assigned.
6. Linker
This chapter describes the operation and the usage of the linker.
The application name of the linker is hlink. In most instances it will not be necessary to invoke the linker directly,
as the assembler driver, pic-as, will automatically execute the linker with all the necessary arguments. Using the
linker directly is not simple, and should be attempted only by those with a sound knowledge of the requirements of
the linking process. If psects are not linked correctly, code failure can result.
6.1 Operation
A command to the linker takes the following form:
hlink [options] files
The options are zero or more case-insensitive linker options, each of which modifies the behavior of the linker in
some way. The files is one or more object files and zero or more library files (.a extension).
The options recognized by the linker are listed in the table below and are discussed in the paragraphs that follow.
Table 6-1. Linker Command-line Options
Option Effect
-Aclass=low-high ,... Specify address ranges for a class.
...........continued
Option Effect
-Qprocessor Specify the device type (for cosmetic reasons only).
-Sclass=limit[,bound] Specify address limit, and start boundary for a class of psects.
If the standard input is a file, then this file is assumed to contain the command-line argument. Lines can be broken by
leaving a backslash \ at the end of the preceding line. In this fashion, hlink commands of almost unlimited length
can be issued. For example, a link command file called x.lnk and containing the following text:
-Z -Ox.o -Mx.map \
-Ptext=0,data=0/,bss,nvram=bss/. \
x.o y.o z.o
Several linker options require memory addresses or sizes to be specified. The syntax for all of these is similar. By
default, the number is interpreted as a decimal value. To force interpretation as a HEX number, a trailing H, or h,
should be added. For example, 765FH will be treated as a HEX number.
To build projects you will typically use either the MPLAB XC8 C compiler (xc8-cc) driver or the MPLAB XC8 PIC
Assembler (pic-as) driver. These will call the linker for you, passing it a set of default linker options. If you need to
modify or supply additional linker options when using a driver, use either the -Wl (see 3.4.35. Wl: Pass Option To
The Linker, Option) or -Xlinker (see 3.4.39. Xlinker Option) driver options, which will pass on the suboption to the
linker application when it is executed.
specifies that the class called CODE represents the two distinct address ranges shown.
Psects can be placed anywhere in these ranges by using the -P option and the class name (see 6.1.19. P: Position
Psect), for example:
-PmyText=CODE
will place the myText psect somewhere in the memory ranges defined by the CODE class. Alternatively, any psect
that is associated with the CODE class when it is defined (see 4.9.47.3. Class Flag) will automatically be linked into
this range, unless it is explicitly located by another option.
Where multiple same-sized, contiguous address ranges are required, they can be specified with a repeat count
following an x character. For example:
-ACODE=0h-0FFFFhx16
specifies that there are 16 contiguous ranges, each 64k bytes in size, starting from address zero (0x0-FFFF,
0x10000-1FFFF, etc.). Even though the address ranges are contiguous, no psect will straddle a boundary between
ranges, or in other words psects linked into the class will be wholly positioned in the range 0x0-FFFF or within the
range 0x10000-1FFFF etc. Linking psects in such a class might yield a different placement to the case where they
were linked into a class defined by:
-ACODE=0h-0FFFFFh
for example, which defines the same total address range but which does not include 64k boundaries.
The -A linker option can also specify an entry range, which is typically used for placement of code psects on
Baseline devices. For example, the class called ENTRY defined as follows:
-AENTRY=00h-0FFh-01FFh,0200h-02FFh-03FEh
has two ranges, 0x0-1FF and 0x200-2FF. However, the middle address in the option informs the linker that any psect
positioned in these ranges must not start above the second address, that is, any psect linked into this class must start
in the entry ranges 0x0-FF or 0x200-2FF. A psect may extend beyond the entry range, provided the start address
is located within it. Such classes should be used for Baseline devices, where the reachable destinations of call
instructions are restricted. See the MPLAB® XC8 PIC Assembler User's Guide for Embedded Engineers for a more
thorough example of using such classes.
The -A linker option does not specify the memory space associated with the address range. Once a psect is
allocated to a class, the space value of the psect is then assigned to the class (see 4.9.47.18. Space Flag). Nor does
this option assign a delta value to a class. If required (typically for Baseline and Mid-range classes used to hold
executable code), this must be set with the linker's -D option (see 6.1.4. D: Define Class Delta Value).
Type Produces
n No call graph.
c Only critical paths in the call graph.
s Standard, short-form call graph (default).
f Full call graph.
The call graph is generated by the linker, primarily for the purposes of allocating memory to objects in the compiled
stack. See the section, Using the Compiled Stack in this guide for more information. Those routines defining stack
objects that are not overlaid with other stack objects and that are hence contributing to the program's data memory
usage are considered as being on a critical path.
A/10h-4h
where A represents the load address of the segment and / represents division. This means “Take the load address of
the psect, divide by 10 HEX, then subtract 4.” This form can be modified by substituting N for A, * for / (to represent
multiplication) and adding, rather than subtracting, a constant. The token N is replaced by the ordinal number of the
segment, which is allocated by the linker. For example:
N*8+4
means “take the segment number, multiply by 8, then add 4.” The result is the segment selector. This particular
example would allocate segment selectors in the sequence 4, 12, 20, ... for the number of segments defined.
The selector of each psect is shown in the map file (see Section 6.4.2.2 “Psect Information Listed by Module”).
-Ppsect=linkaddr+min/loadaddr+min,psect=linkaddr/loadaddr,...
All values can be omitted, in which case a default will apply, depending on previous values. The link address of a
psect is the address at which it can be accessed at runtime. The load address is the address at which the psect starts
within the output file (HEX or binary file etc.), but it is rarely used by 8-bit PIC devices. The addresses specified can
be numerical addresses, the names of other psects, classes, or special tokens.
This argument to this option often contains a comma, so it you are passing this option to the linker from either the
MPLAB XC8 C compiler (xc8-cc) or the MPLAB XC8 PIC Assembler (pic-as) drivers, you might need to use the
-Xlinker driver option (see 3.4.39. Xlinker Option) rather than the -Wl option (see 3.4.35. Wl: Pass Option To The
Linker, Option) to avoid the comma in the option argument causing unexpected results.
Examples of the basic and most common forms of this option are:
-Ptext10=02000h
which places (links) the starting address of psect text10 at address 0x2000;
-PmyData=AUXRAM
which places the psect myData anywhere in the range of addresses specified by the linker class AUXRAM (which
would need to be defined using the -A option, see 6.1.1. A: Define Linker Class Option), and
-PstartCode=0200h,endCode
which places endCode immediately after the end of startCode, which will start at address 0x200.
The additional variants of this option are rarely needed; but, are described below.
If a link or load address cannot be allowed to fall below a minimum value, the +min, suffix indicates the minimum
address.
If the link address is a negative number, the psect is linked in reverse order with the top of the psect appearing at the
specified address minus one. Psects following a negative address will be placed before the first psect in memory.
If the load address is omitted entirely, it defaults to the link address. If the slash / character is supplied with no
address following, the load address will concatenate with the load address of the previous psect. For example, after
processing the option:
-Ptext=0,data=0/,bss
the text psect will have a link and load address of 0; data will have a link address of 0 and a load address following
that of text. The bss psect will concatenate with data in terms of both link and load addresses.
A load address specified as a dot character, “.” tells the linker to set the load address to be the same as the link
address.
The final link and load address of psects are shown in the map file (see 6.3.2.2. Psect Information Listed By
Module).
-SCODE=400h
Note that to set an upper limit to a psect, this must be set in assembler code using the psect limit flag, (see
4.9.47.8. Limit Flag).
If the bound (boundary) argument is used, the class of psects will start on a multiple of the bound address. This
example below places the FARCODE class of psects at a multiple of 1000h, but with an upper address limit of 6000h.
-SFARCODE=6000h,1000h
6.1.28 Disl
The --disl=messages option is mainly used by the command-line driver, pic-as, to disable particular message
numbers. It takes a comma-separate list of message numbers that will be disabled during compilation.
6.1.29 Edf
The --edf=file specifies the message description file to use when displaying warning or error messages. The
argument to this option should be the full path to the message file. Most applications contain an internal copy of
the message file, so this option is not normally required. Use this option if you want to specify an alternate file with
updated contents.
A message description file is shipped with the MPLAB XC8 C Compiler and is located in the compiler's pic/dat
directory. The shipped file is called buildnumber_en.msgs. A build date (yyyymmdd format) will appear at the
beginning of the build number and may help you identify more up to date files.
6.1.30 Emax
The --emax=number option is mainly used by the command-line driver, pic-as, to specify the maximum number of
errors that can be encountered before the assembler terminates. The default number is 10 errors.
This option is applied if compiling using pic-as, the command-line driver, and the -fmax-errors driver option.
Action Response
error Trigger an error message
warn Truncate the value to fit and trigger a warning message.
lstwarn Truncate the value to fit and insert a warning marker into
the assembly list file where the overflow occurred. (the
default response when used with pic-as)
ignore Truncate the value to fit and continue with no notification
of the fact.
The warn and lstwarn actions can both be selected with this option, in which case they must be separated by a
colon (:), for example --fixupoverflow=warn:lstwarn.
If an assembly list file has been requested using the -Wa,-a assembler option and the lstwarn action has been
requested, a warning message will be inserted into the list file before the instruction or directive that contains the
symbol being fixed up. The message will appear similar to:
13 003FF4 6F14 movwf _bar,b
14 003FF6
warning: (2090) fixup overflow storing 0x202 in 1 byte
5102 movf _foo,w,b
which shows an overflow associated with the symbol _foo. In this instance, the symbol has been resolved to the
value 0x202, but there are only 7 bits in the movf instruction to hold the address offset of the file register being
accessed. The linker has truncated the value 0x202 to a 7-bit quantity (0x02) and inserted this into the program
image forming the opcode 0x5102.
If warning messages are inserted into a list file, a single advisory message will be issued by the assembler for each
affected list file to alert you to this action. If the lstwarn action was specified, but an assembly list file was not
actually requested, then an alternate warning message will be issued by the assembler.
Fixup overflows in hand-written assembly programs might indicate some sort of error in how the code was written or
linked. It is commonly associated with the address of symbols in PIC programs that have not been masked to remove
the banking or paging information. In this case, if you do not wish to mask addresses manually (see the Address
Masking section in this guide), this option can be used to truncate the addresses and allow the program to build. It
should be stressed that this option will, however, suppress the error message associated with any fixup overflow. It is
recommended that an action of warn, or lstwarn be used so that you can monitor which instructions are affected. If
there is some other erroneous situation in your program, using this option will in no way address the underlying issue.
6.1.32 Norlf
Use of the --norlf option prevents the linker applying fixups to the assembly list file produced by the assembler.
This option is normally using by the command line driver, pic-as, when performing pre-link stages, but is omitted
when performing the final link step so that the list file shows the final absolute addresses.
If you are attempting to resolve fixup errors, this option should be disabled so as to fix up the assembly list file and
allow absolute addresses to be calculated for this file. If the assembler driver detects the presence of a preprocessor
macro __DEBUG, which is equated to 1, then this option will be disabled when building. This macro is set when
choosing a Debug build in MPLAB X IDE. So, always have this option selected if you encounter such errors.
6.1.33 Ver
The --ver option prints information stating the version and build of the linker. The linker will terminate after
processing this option, even if other options and files are present on the command line.
the udata psect has already been associated with the RAM linker class and will be linked anywhere in free memory
associated with that class.
If you have created your own psect, you can associate it with any of the existing linker classes provided by the PIC
Assembler by using the class flag with the psect definition. In the following example, a psect has been created by
the programmer to use instead of udata.
PSECT machData,space=1,class=MDATA
myVar:
DS 2
This psect uses a new class, MDATA, which will need to be defined by a linker option. To do that, use, for example,
the driver option, -Wl,-AMDATA=050h-05fh, which passes the -A linker option directly to the linker and which will
associate the specified address range with the MDATA class.
There are, however, times when a psect must be placed at a specific address. The reset vector code is one good
example, as are interrupt routines. In this case, you will need to use a -p linker option to place the psect at the
desired location. This might be as simple as providing an absolute address, for example using the driver option
-Wl,-pInterrupt=08h to place the psect called Interrupt at address 8, but there are more advanced usages of
this option.
Check the MPLAB® XC8 PIC Assembler User's Guide for full details concerning the psects and linker classes
provided by the PIC Assembler, as well as the linker and driver options mentioned in this section.
6.3.2 Contents
The sections in the map file, in order of appearance, are as follows.
• The assembler name and version number.
• A copy of the command line used to invoke the linker.
• The version number of the object code in the first file linked.
• The machine type.
• A psect summary sorted by the psect’s parent object file.
• A psect summary sorted by the psect’s CLASS.
• A segment summary.
• Unused address ranges summary.
• The symbol table.
• Information summary for each function.
• Information summary for each module.
Portions of an example map file, along with explanatory text, are shown in the following sections.
startup.o main.o
The information following Linker command line: shows all the command-line options and files that were passed to
the linker for the last build. Remember, these are linker options, not command-line driver options.
The linker options are necessarily complex. Fortunately, they rarely need adjusting from their default settings. They
are formed by the command-line driver, pic-as, based on the selected target device and the specified driver
options. You can often confirm that driver options were valid by looking at the linker options in the map file. For
example, if you ask the driver to reserve an area of memory, you should see a change in the linker options used.
If the default linker options must be changed, this can be done indirectly through the driver using the driver -Wl
option (see 3.4.35. Wl: Pass Option To The Linker, Option). If you use this option, always confirm the change
appears correctly in the map file.
Under this on the far left is a list of object files (.o extension). Both object files that were generated from source
modules and those extracted from object library files (.a extension) are shown. In the latter case, the name of the
library file is printed before the object file list.
Next to the object file are the psects (under the Name column) that were linked into the program from that object file.
Useful information about that psect is shown in the columns, as follows.
The linker deals with two kinds of addresses: link and load. Generally speaking, the Link address of a psect is the
address by which it is accessed at runtime.
The Load address, which is often the same as the link address, is the address at which the psect starts within the
output file (HEX or binary file etc.). If a psect is used to hold bits, the load address is irrelevant and is used to hold the
link address (in bit units) converted into a byte address instead.
The Length of the psect is shown in the units that are used by that psect.
The Selector is less commonly used and is of no concern when compiling for PIC devices.
The Space field is important as it indicates the memory space in which the psect was placed. For Harvard
architecture machines, with separate memory spaces (such as the PIC devices), this field must be used in
conjunction with the address to specify an exact storage location. A space of 0 indicates the program memory
and a space of 1 indicates the data memory (see 4.9.47.18. Space Flag).
The Scale of a psect indicates the number of address units per byte. This remains blank if the scale is 1 and shows 8
for psects that hold bit objects. The load address of psects that hold bits is used to display the link address converted
into units of bytes, rather than the load address (see 4.9.47.2. Bit Flag).
For example, the following appears in a map file.
This indicates that one of the files that the linker processed was called ext.o.
This object file contained a text psect, as well as psects called bss and rbit.
The psect text was linked at address 3A and bss at address 4B. At first glance, this seems to be a problem, given
that text is 22 words long. However, they are in different memory areas, as indicated by the space flag (0 for text
and 1 for bss), and so they do not even occupy the same memory space.
The psect rbit contains bit objects, and this can be confirmed by looking at the scale value, which is 8. Again, at
first glance it seems that there could be an issue with rbit linked over the top of bss. Their space flags are the
same, but since rbit contains bit objects, its link address is in units of bits. The load address field of rbit psect
displays the link address converted to byte units, i.e., 50h/8 => Ah.
Under this are the class names followed by those psects which belong to this class (see 4.9.47.3. Class Flag). These
psects are the same as those listed by module in the above section; there is no new information contained in this
section, just a different presentation.
The name of a segment is derived from the psect in the contiguous group with the lowest link address. This can lead
to confusion with the psect with the same name. Do not read psect information from this section of the map file.
Again, this section of the map file can be ignored.
and is followed by a list of classes and the memory that is still available in each class. If there is more than one
memory range available in a class, each range is printed on a separate line. Any paging boundaries located within
a class are not displayed. But the column Largest block shows the largest contiguous free space (which takes into
account any paging in the memory range). If you are looking to see why psects cannot be placed into memory (e.g.,
cant-find-space type errors) then this is important information to study.
Note that memory can be part of more than one class, thus the total free space is not simply the addition of all the
unused ranges.
Symbol Table
Assembly symbols are made global via the GLOBAL assembler directive, see 4.9.29. Global Directive for more
information.
Linker-defined symbols act like EQU directives. However, they are defined by the linker during the link process, and
no definition for them appears in any source or intermediate file (see 5.4. Linker-Defined Symbols).
Each symbol is shown with the psect in which it is defined and the value (usually an address) it has been assigned.
There is not any information encoded into a symbol to indicate whether it represents code or data – nor in which
memory space it resides.
If the psect of a symbol is shown as (abs), this implies that the symbol is not directly associated with a psect. Such is
the case for absolute C variables, or any symbols that are defined using an EQU directive in assembly.
Note that a symbol table is also shown in each assembler list file. These differ to that shown in the map file as they
also list local symbols and they only show symbols defined in the corresponding module.
The module name is listed (main.c in the above example). The special module name shared is used for data objects
allocated to program memory and to code that is not specific to any particular module.
Next, the user-defined and library functions defined by each module are listed along with the class in which that psect
is located, the psect’s link and load address, and its size (shown as bytes for PIC18 devices and words for other 8-bit
devices).
After the function list is an estimated size of the program memory used by that module.
7. Utilities
This chapter discusses some of the utility applications that are bundled with the assembler.
The applications discussed in this chapter are those more commonly used, but you do not typically need to
execute them directly. Some of their features are invoked indirectly by the command line driver that is based on
the command-line arguments or MPLAB X IDE project property selections.
7.1 Archiver/Librarian
The archiver/librarian program has the function of combining several intermediate files into a single file, known as a
library archive file. Library archives are easier to manage and might consume less disk space than the individual files
contained in them.
The archiver can build all library archive types needed by the assembler and can detect the format of existing
archives.
Option Effect
-d modules Delete module
-m modules Re-order modules
-p List modules
-r modules Replace modules
-t List modules with symbols
-x modules Extract modules
--target device Specify target device
When replacing or extracting modules, the names of the modules to be replaced or extracted must be specified. If no
names are supplied, all the modules in the archive will be replaced or extracted respectively.
Creating an archive file or adding a file to an existing archive is performed by requesting the archiver to replace the
module in the archive. Since the module is not present, it will be appended to the archive.
The archiver creates library archives with the modules in the order in which they were given on the command line.
When updating an archive, the order of the modules is preserved. Any modules added to an archive will be appended
to the end.
The ordering of the modules in an archive is significant to the linker. If an archive contains a module that references a
symbol defined in another module in the same archive, the module defining the symbol should come after the module
referencing the symbol.
When using the -d option, the specified modules will be deleted from the archive. In this instance, it is an error not to
supply any module names.
The -p option will list the modules within the archive file.
The -m option takes a list of module names and re-orders the matching modules in the archive file so that they have
the same order as the one listed on the command line. Modules that are not listed are left in their existing order, and
will appear after the re-ordered modules.
7.1.1.1 Examples
Here are some examples of usage of the librarian. The following command:
creates a library called myLib.a that contains the modules ctime.o and init.o
The following command deletes the object module a.o from the library lcd.a:
7.2 Hexmate
The Hexmate application is a post-link-stage utility designed to manipulate Intel HEX files.
Hexmate is automatically invoked by the assembler driver, but it can also be executed as a stand-alone application, if
required.
where file1.hex through to fileN.hex forms a list of input Intel HEX files to merge using Hexmate. The
options can appear anywhere on the command line and are tabulated below.
If only one HEX file is specified, no merging takes place, but other actions can be performed on the HEX file, as
specified by the options.
Hexmate can read and write common 8-, 16-, and 32-bit named formats, which contain only specific subsets of
record types. The formats are discussed in 7.2.2.16. Format.
Table 7-2. Hexmate Command-line Options
Option Effect
--edf=file Specify the message description file.
--emax=n Set the maximum number of permitted errors before terminating.
--msgdisable=number Disable messages with the numbers specified.
--sla=address Set the start linear address for a type 5 record.
--ssa=address Set the start segment address for a type 3 record.
--ver Display version and build information then quit.
-addressing=units Set address fields in all Hexmate options to use word addressing or other.
-break Break continuous data so that a new record begins at a set address.
-ck=spec Calculate and store a hash value.
-fill=spec Program unused locations with a known value.
-find=spec Search and notify if a particular code sequence is detected.
-find=spec,delete Remove the code sequence if it is detected (use with caution).
-find=spec,replace=spec Replace the code sequence with a new code sequence.
-format=type Specify maximum data record length or select INHX variant.
-help Show all options or display help message for specific option.
-logfile=file Save Hexmate analysis of output and various results to a file.
-mask=spec Logically AND a memory range with a bitmask.
-ofile Specify the name of the output file.
-serial=spec Store a serial number or code sequence at a fixed address.
-size Report the number of bytes of data contained in the resultant HEX image.
-string=spec Store an ASCII string at a fixed address.
-strpack=spec Store an ASCII string at a fixed address using string packing.
-wlevel Adjust warning sensitivity.
+ Prefix to any option to overwrite other data in its address range, if necessary.
The format or assumed radix of values associated with options are detailed with each option description. Note
that any address fields specified in these options are to be entered as HEX file addresses, unless you use the
-addressing option to change this.
A range restriction can be applied with the specification rStart-End, where Start and End are both assumed to
be hexadecimal values. Hexmate will only process data within the address range restriction. For example:
r100-1FF,myfile.hex
will use myfile.hex as input, but only process data which is addressed within the range 0x100-1FF (inclusive) from
that file.
An address shift can be applied with the specification sOffset, where Offset is assumed to be an unqualified
hexadecimal value. If an address shift is used, data read from this HEX file will be shifted (by the offset specified) to a
new address in the output file. The offset can be either positive or negative. For example:
r100-1FFs2000,myfile.hex
will shift the block of data from 0x100-1FF in myfile.hex to the new address range 0x2100-21FF in the output.
Be careful when shifting sections of executable code. Program code should only be shifted if it is position
independent.
will have the data specified by the -string option placed at address 0x1000 in the output file; however:
will copy the data contained in the input HEX file at address 0x1000 into the final output.
Without this option, Hexmate will issue an error if two sources try to store differing data at the same location.
7.2.2.3 Edf
The --edf=file specifies the message description file to use when displaying warning or error messages. The
argument to this option should be the full path to the message file. Most applications contain an internal copy of
the message file, so this option is not normally required. Use this option if you want to specify an alternate file with
updated contents.
A message description file is shipped with the MPLAB XC8 C Compiler and is located in the compiler's pic/dat
directory. The shipped file is called buildnumber_en.msgs. A build date (yyyymmdd format) will appear at the
beginning of the build number and may help you identify more up to date files.
7.2.2.4 Emax
The --emax=num option sets the maximum number of errors Hexmate will display before execution is terminated,
e.g., --emax=25. By default, up to 20 error messages will be displayed.
7.2.2.5 Msgdisable
The --msgdisable=number option allows error, warning or advisory messages to be disabled during execution of
Hexmate.
The option is passed a comma-separated list of message numbers that are to be disabled. Any error message
numbers in this list are ignored unless they are followed by an :off argument. For example:
--msgdisable=2031,963
When this option is used, any input SLA records present in the input files are checked for correct syntax and
checksum. An error will be issued if they are not valid. These SLA records will then be discarded with no warning
message. If the output file format is not INHX32 or INHX032, a warning will be issued and no SLA record will be
written; otherwise, one SLA record only will appear in the output, containing the value specified by the option.
If this option is not used, any input SLA records present in the input files are checked for correct syntax and
checksum. If there is no discrepancy between the addresses specified by these records, one and only one SLA
record with that address is written to the output. If there is a conflict between SLA records present in the input files, a
warning message will be emitted and no SLA record will appear in the output. If there are no SLA records present in
the input files, no SLA record will be written to the output.
When this option is used, any SSA records present in the input files are checked for correct syntax and checksum.
An error will be issued if they are not valid. These SSA records will then be discarded with no warning message. If
the output file format is not INHX16, a warning will be issued and no SSA record will be written; otherwise, one SSA
record only will appear in the output, containing the value specified by the option.
If this option is not used, any SSA records present in the input files are checked for correct syntax and checksum.
If there are no discrepancy between the addresses specified by these records, one and only one SSA record with
that address is written to the output. If there is a conflict between SSA records present in the input files, a warning
message will be emitted and no SSA record will appear in the output. If there are no SSA records present in the input
files, no SSA record will be written to the output.
7.2.2.8 Ver
The --ver option will ask Hexmate to print version and build information and then quit.
7.2.2.9 Addressing
The -addressing=units option allows the addressing units of any addresses in Hexmate's command line options
to be changed from the default value of 1 to a maximum value of 4.
By default, all address arguments specified in Hexmate options are assumed to be byte addresses, as used by
Intel HEX files. For example, in the option -mask=0F@0-FF, the mask will be performed on any HEX file data from
address 0x0 to address 0xFF. In some device architectures, the native addressing format can be something other
than byte addressing. For example, a HEX file might contain the bytes 0x0F and 0x55 at addresses 0x200 and
0x201, respectively, but when this HEX file is loaded into a Mid-range PIC device, these bytes will form one word at
address 0x100 in the device. In this case, the word value at each device address expands into two byte values at
separate addresses in the HEX file. If you prefer to use device addresses with Hexmate options, use this option to
specify the mapping between HEX file addresses and device addresses.
This option takes one parameter that indicates the number of HEX file bytes that will be stored in each device
address location. The parameter may range from the values 1 thru 4. For 8-bit AVR devices, Baseline, Mid-range,
and 24-bit PIC devices, an addressing unit of 2 can be used, if desired, for example, -addressing=2. You may then
specify device addresses in all Hexmate options. For all other Microchip devices, you would typically use the default
addressing unit of 1 byte, for example use -addressing=1 or omit this option entirely. For these devices, the HEX
file and device addresses for any location are the same and no mapping is required.
7.2.2.10 Break
The -break option takes a comma-separated list of unqualified hexadecimal addresses. If any of these addresses
are encountered in the HEX file, the current data record will conclude and a new data record will recommence from
the nominated address.
For example, if the output of Hexmate normally contains:
:100000000EEF0AF03412ADDEADDEADDEADDEADDEFC
:10001000ADDEADDEADDEADDEADDEADDEADDEADDE88
:10002000ADDEADDEADDEADDEADDEADDEADDEADDE78
...
Breaking data records can create a distinction between functionally different areas of the program space. Some HEX
file readers depend on records being arranged this way.
-ck=start-end@dest[+offset][wWidth][tCode[.Base]][gAlgorithm][pPolynomial]
[rRevWidth][sSkipWidth[.SkipBytes]][oXORvalue]
where:
• start and end specify the hexadecimal address range over which the hash will be calculated. If these
addresses are not a multiple of the data width for checksum and Fletcher algorithms, the value zero will be
padded into the relevant input word locations that are missing.
• dest is the hexadecimal address where the hash result will be stored. This address cannot be within the range
of addresses over which the hash is calculated.
• offset is an optional initial hexadecimal value to be used in the hash calculations. It is not used with SHA
algorithms.
• Width is optional and specifies the decimal width of the result. Results can be calculated for byte-widths
of 1 to 4 bytes for most algorithms, but it represents the bit width for SHA algorithms. If a positive width is
requested, the result will be stored in big-endian byte order. A negative width will cause the result to be stored
in little-endian byte order. If the width is left unspecified, the result will be 2 bytes wide and stored in little-endian
byte order. This width argument is not required with any Fletcher algorithm, as they have fixed widths, but it may
be used to alter the default endianism of the result.
• Code is an optional hexadecimal code sequence that will trail each byte in the result. Use this feature if you
need each byte of the hash result to be embedded within an instruction or if the hash value has to be padded to
allow the device to read it at runtime. For example, t34 will embed each byte of the result in a retlw instruction
(bit sequence 0x34xx) on Mid-range PIC devices. If the code sequence specifies multiple bytes, these are
stored in big-endian order after the hash bytes, for example tAABB will append 0xAA immediately after the hash
byte and 0xBB at the following address. The trailing code specification t0000 will store two 0x00 bytes after
each byte of the hash. The code sequence argument can be optionally followed by .Base, where Base is the
number of bytes of hash to be output before the trailing code sequence is appended. A specification of t11.2,
for example, will output the byte 0x11 after each two bytes of the hash result.
• Algorithm is a decimal integer to select which Hexmate hash algorithm to use to calculate the result. A list of
selectable algorithms is provided in the table below. If unspecified, the default algorithm used is 8-bit checksum
addition (algorithm 1).
• Polynomial is a hexadecimal value which is the polynomial to be used if you have selected a CRC algorithm.
• RevWidth is an optional reverse word width. If this is non-zero, then bytes within each word are read in reverse
order when calculating a hash value. Words are aligned to the addresses in the HEX file. At present, the width
must be 0 or 2. A zero width disables the reverse-byte feature, as if the r suboption was not present. This
suboption is intended for situations when Hexmate is being used to match a CRC produced by a PIC hardware
CRC module that uses the Scanner module to stream data to it. This feature will work with all hash types, but
has no effect when using any checksum algorithm (algorithms -4 thru 4).
• SkipWidth is an optional skip word width. If this is non-zero, then the byte at the highest address within each
word is skipped for the purposes of calculating a hash value. Words are aligned to the addresses in the HEX
file. At present, the width must be 0 (which disables the skip feature, as if the s suboption was not present) or
greater than 1. This skip width argument can be optionally followed by .SkipBytes, where SkipBytes is a
number representing the number of bytes to skip in each word, for example s4.2 will skip the two bytes at the
highest addresses in each 4-byte word. To avoid processing the 'phantom' 0x00 bytes added to HEX files by the
MPLAB XC16 C Compiler in hash calculations, use s4.
• XORvalue is a hexadecimal value that will be XORed with the hash result before it stored.
The single letter argument tokens are case insensitive, so for example w2 and W2 are both valid width arguments to
this option.
A typical example of the use of this option to calculate a checksum is:
-ck=0-1FFF@2FFE+2100w-2g2
This will calculate a checksum (16-bit addition) over the range 0 to 0x1FFF and program the checksum result at
address 0x2FFE. The checksum value will be offset by 0x2100. The result will be two bytes wide and stored in
little-endian format.
Note that the reverse and skip features act on words that are aligned to the HEX file addresses, not to the starting
byte of data in the sequence being processed. In other words, the positions of the words are not affected by the start
and end addresses specified in the -ck option. Consider this option:
-ck=0-5@100w2g5p1021s2
which specifies that when calculating the hash value, every second byte be skipped (s2) over HEX addresses 0 thru
5. If it is acting on the HEX record (data underlined):
:1000000064002500030A750076007700780064001C
the hash will be calculated from the (hexadecimal) bytes 64, 25, and 03. Processing the same HEX record with an
option that uses a different start and end address range (1 thru 6):
-ck=1-6@100w2g5p1021s2
the hash will be calculated from the (hexadecimal) bytes 25, 03, and 75. These features attempt to mimic data read
limitations of code running on the device, and thus the words they use are aligned with device addresses, which are
in turn aligned to HEX file addresses.
Table 7-3. Hexmate Hash Algorithm Selection
...........continued
Selector Algorithm Description
4 Addition of 32 bit values from initial value.
5 Cyclic redundancy check (CRC).
7 Fletcher’s checksum (8 bit calculation, 2-byte result width).
8 Fletcher’s checksum (16 bit calculation, 4-byte result width).
10 SHA-2 (currently only SHA256 is supported).
See 7.2.3. Hash Value Calculations for more details about the algorithms that are used to calculate hashes.
7.2.2.12 Fill
The -fill option is used for filling unused (unspecified) memory locations in a HEX file with a known value. The
usage of this option is:
-fill=[wwidth:]fill_expr@address[:end_address]
wwidth signifies the decimal width of each constant in the fill_expr and can range from 1 thru 9. If this
width is not specified, the default value is two bytes. For example, -fill=w1:0x55@0:0xF with
fill every unused byte between address 0 and 0xF with the byte value 0x55, for example:
:10000000FBEF3FF0555555555555555555555555DB
whereas -fill=w2:0x55@0:0xF with fill every unused byte between the same addresses with
the value 0x0055, for example:
:10000000FBEF3FF0550055005500550055005500D9
fill_expr defines the values to fill and consists of const, which is a base value to place in the first memory
location and optionally with increment, which indicates how this base value should change after
each use. If the base value specifies more than one byte, these are stored in little-endian byte
order. These following show the possible fill expressions:
• const fill memory with a repeating constant; i.e., -fill=0xBEEF@0-0x1FF fills unused
locations starting at address 0 with the values 0xBEEF, 0xBEEF, 0xBEEF, 0xBEEF, etc., for
example:
:10000000FBEF3FF0EFBEEFBEEFBEEFBEEFBEEFBEC9
Note that const increments with each location scanned, regardless of whether that location
is populated or unused.
• const-=increment fill memory with a decrementing constant; i.e.,-fill=0xBEEF-
=0x10@0:0x1FF attempts to fills with the values 0xBEEF, 0xBEDF, 0xBECF, 0xBEBF, etc.,
for example:
:10000000FBEF3FF0CFBEBFBEAFBE9FBE8FBE7FBE79
Note that const decrements with each location scanned, regardless of whether that location
is populated or unused.
@address fills a specific address with fill_expr; for example, -fill=0xBEEF@0x1000 puts the byte
value 0xEF at addresses 0x1000 when the addressing value is set to 1.
:01100000EF00
If the -addressing=2 option had been additionally used in the above example, the fill option
would place 2-bytes at address 0x2000 and 0x2001.
:02200000EFBE31
:end_address optionally specifies an end address of memory to be filled with fill_expr; for example, -
fill=0xBEEF@0xF0:0xFF puts 0xBEEF in unused addresses between 0 and 0xFF, inclusive.
:1000F000EFBEEFBEEFBEEFBEEFBEEFBEEFBEEFBE98
If the address range (multiplied by the -addressing value) is not a multiple of the fill value width,
the final location will only use part of the fill value, and a warning will be issued.
The fill values are word-aligned so they start on an address that is a multiple of the fill width. Should the fill value
be an instruction opcode, this alignment ensures that the instruction can be executed correctly. Similarly, if the total
length of the fill sequence is larger than 1 (and even if the specified width is 1), the fill sequence is aligned to that total
length. For example the following fill option, which specifies 2 bytes of fill sequence and a starting address that is not
a multiple of 2:
-fill=w1:0x11,0x22@0x11001:0x1100c
will result in the following HEX record, where the starting address was filled with the second byte of the fill sequence
due to this alignment.
:0C100100221122112211221122112211B1
Compare that to when the option is -fill=w1:0x11,0x22@0x11000:0x1100c, which does specify a starting
address that is a multiple of 2.
:0D10000011221122112211221122112211A0
All fill constants (excluding the width specification) can be expressed in (unsigned) binary, octal, decimal or
hexadecimal, as per normal C syntax, for example, 1234 is a decimal value, 0xFF00 is hexadecimal and FF00
is illegal.
7.2.2.13 Find
The -find=opcode option is used to detect and log occurrences of an opcode or code sequence. The usage of this
option is:
-find=Findcode[mMask]@Start-End[/Align][w][t”Title”]
where:
• Findcode is the hexadecimal code sequence to search for. For example, to find a clrf instruction with the
opcode 0x01F1, use 01F1 as the sequence. In the HEX file, this will appear as the byte sequence F1 01, that is
0xF1 at HEX address 0 and 0x01 at HEX address 1.
• Mask is optional. It specifies a bit mask applied over the Findcode value to allow a less restrictive search. It is
entered in little endian byte order.
• Start and End limit the address range to search.
• Align is optional. It specifies that a code sequence can only match if it begins on an address that is a multiple
of this value.
• w, if present, will cause Hexmate to issue a warning whenever the code sequence is detected.
• Title is optional. It allows a title to be given to this code sequence. Defining a title will make log-reports and
messages more descriptive and more readable. A title will not affect the actual search results.
All numerical arguments are assumed to be hexadecimal values.
Here are some examples.
The option -find=1234@0-7FFF/2w will detect the code sequence 1234h (stored in the HEX file as 34 12) when
aligned on a 2 (two) byte address boundary, between 0h and 7FFFh. w indicates that a warning will be issued each
time this sequence is found.
In this next example, -find=1234M0F00@0-7FFF/2wt”ADDXY”, the option is the same as in last example but the
code sequence being matched is masked with 000Fh, so Hexmate will search for any of the opcodes 123xh, where
x is any digit. If a byte-mask is used, it must be of equal byte-width to the opcode it is applied to. Any messaging
or reports generated by Hexmate will refer to this opcode by the name, ADDXY, as this was the title defined for this
search.
When requested, a log file will contain the results of all searches. The -find option accepts whole bytes of HEX data
from 1 to 8 bytes in length. Optionally, -find can be used in conjunction with replace or delete (as described
separately).
-find=ff@7fe0-7fff,delete
This function should be used with extreme caution and is not normally recommended for removal of executable code.
-find=spec,replace=Code[mMask]
where:
• Code is a hexadecimal code sequence to replace the sequences that match the -find criteria.
• Mask is an optional bit mask to specify which bits within Code will replace the code sequence that has been
matched. This can be useful if, for example, it is only necessary to modify 4 bits within a 16-bit instruction. The
remaining 12 bits can masked and left unchanged.
For example:
-find=ff@7fe0-7fff,replace=55
7.2.2.16 Format
The -format=type[,length] option can be used to specify a particular named format of INHX file to output
and/or to adjust the maximum record length.
The typeargument specifies a particular named INHX format to generate, as tabulated below. This option might be
used to change the format of an input file, for example from an INHX16 to an INHX32 file, but the presence of record
types 2, 3, 4, or 5 in the input will prevent conversion to an INHX8 file from any other format. Note that the record
types present in a HEX file solely determine the file's format, for example, if only record types 0 and 1 are present in
a HEX file, then that file is considered to have an INHX8M format; if type 4 or 5 records were also present, then it is
considered to have INHX32 format; if type 2 or 3 and type 4 or 5 records were present, then the file does not conform
to any named format and those records which are not permitted in the specified output format will be removed.
The lengthargument is optional and sets the maximum number of bytes per data record. A valid length is between 1
and 16 decimal, with 16 being the default.
The possible types that are supported by this option are listed below. Note that INHX032 is not an actual named
INHX format. Selection of this type generates an INHX32 file, but will also initialize the upper address information to
zero. This is a requirement of some device programmers.
Table 7-4. HEX file Formats
7.2.2.17 Help
Using -help will list all Hexmate options. Entering another Hexmate option as a parameter of -help will show a
detailed help message for the given option. For example:
-help=string
7.2.2.18 Logfile
The -logfile option saves HEX file statistics to the named file. For example:
-logfile=output.hxl
will analyze the HEX file that Hexmate is generating and save a report to a file named output.hxl.
7.2.2.19 Mask
Use the -mask=spec option to logically AND a memory range with a particular bitmask. This is used to ensure that
the unimplemented bits in program words (if any) are left blank. The usage of this option is as follows:
-mask=hexcode@start-end
where hexcode is a value that will be ANDed with data within the start to end address range. All values are
assumed to be hexadecimal. Multibyte mask values can be entered in little endian byte order.
-oprogram.hex
will save the resultant output to program.hex. The output file can take the same name as one of its input files but,
by doing so, it will replace the input file entirely.
If this option is used without a filename, no output is produced, which may be useful if you want to use Hexmate to
only show the size of a HEX file, for example. If this option is not used at all, the content of the output HEX file is
printed to the standard output stream.
7.2.2.21 Serial
The -serial=specs option will store a particular HEX value sequence at a fixed address. The usage of this option
is:
-serial=Code[+/-Increment]@Address[+/-Interval][rRepetitions]
where:
• Code is a hexadecimal sequence to store. The first byte specified is stored at the lowest address.
• Increment is optional and allows the value of Code to change by this value with each repetition (if requested).
• Address is the location to store this code, or the first repetition thereof.
• Interval is optional and specifies the address shift per repetition of this code.
• Repetitions is optional and specifies the number of times to repeat this code.
All numerical arguments are assumed to be hexadecimal values, except for the Repetitions argument, which is
decimal value by default.
For example:
-serial=000001@EFFE
-serial=0000+2@1000+10r5
will store 5 codes, beginning with value 0000 at address 0x1000. Subsequent codes will appear at address intervals
of +0x10 and the code value will change in increments of +0x2.
7.2.2.22 Size
Using the -size option will report the number of bytes of data within the resultant HEX image to standard output.
The size will also be recorded in the log file if one has been requested.
7.2.2.23 String
The -string option will embed an ASCII string at a fixed address. The usage of this option is:
-string@Address[tCode]=”Text”
where:
• Address is assumed to be a hexadecimal value representing the address at which the string will be stored.
• Code is optional and allows a byte sequence to trail each byte in the string. This can allow the bytes of the string
to be encoded within an instruction.
• Text is the string to convert to ASCII and embed.
For example:
will store the ASCII data for the string, My favorite string (including the null character terminator), at address 0x1000.
And again:
will store the same string, trailing every byte in the string with the HEX code 0x34.
7.2.2.24 Strpack
The -strpack=spec option performs the same function as -string, but with two important differences.
Whereas -string stores the full byte corresponding to each character, -strpack stores only the lower seven bits
from each character. Pairs of 7-bit characters are then concatenated and stored as a 14-bit word rather than in
separate bytes. This is known as string packing. This is often useful for Mid-range PIC devices, where the program
memory is addressed as 14-bit words. If you intend to use this option, you must ensure that the encoded characters
are fully readable and correctly interpreted at runtime.
The second difference between these two options is that the t specifier usable with -string is not applicable with
the -strpack option.
Baseline and Mid-range PIC devices must store data in program memory using retlw instructions. Thus they need
one instruction to store each byte of the hash value calculated by Hexmate. When executing Hexmate explicitly, use
the t34 suboption to the -ck option to have Hexmate process store each bytes as part of a retlw instruction.
The dsPIC and PIC24 devices cannot read the full width of their program memory and data to be loaded to this
memory is typically stored in 2-byte chunks per every 4 bytes of HEX file data.When executing Hexmate explicitly,
use the t0000.2 suboption to the -ck option to have Hexmate store two bytes of the hash value in the lower half of
each 4-bytes of the HEX file, with the upper bytes set to zero.
#include <stdint.h>
typedef uint8_t read_t; // size of data values read and summed
typedef uint16_t result_t; // size of checksum result
The read_t and result_t type definitions should be adjusted to suit the data read/sum width and checksum result
width, respectively. If you never use an offset, that parameter can be removed and chksum assigned 0 before the
loop.
Here is how this function might be used when, for example, a 2-byte-wide checksum is to be calculated from the
addition of 1-byte-wide values over the address range 0x100 to 0x7fd, starting with an offset of 0x20. The checksum
is to be stored at 0x7fe and 0x7ff in little endian format.
When executing Hexmate explicitly, use the option:
-ck=100-7fd@7fe+20g1w-2
Adapt the following MPLAB XC8 code snippet for PIC devices, which calls ck_add() and compares the runtime
checksum with that stored by Hexmate at compile time.
This code uses the placeholder array, ck_range, to represent the memory over which the checksum is calculated
and the variable hexmate is mapped over the locations where Hexmate will have stored its checksum result. Being
extern and absolute, neither of these objects consume additional device memory. Adjust the addresses and sizes of
these objects to match the option you pass to Hexmate.
Hexmate can calculate a checksum over any address range; however, the test function, ck_add(), assumes that the
start and end address of the range being summed are a multiple of the read_t width. This is a non-issue if the size
of read_t is 1. It is recommended that your checksum specification adheres to this assumption, otherwise you will
need to modify the test code to perform partial reads of the starting and/or ending data values. This will significantly
increase the code complexity.
#include <stdint.h>
typedef uint8_t read_t; // size of data values read and subtracted
typedef uint16_t result_t; // size of checksum result
Here is how this function might be used when, for example, a 4-byte-wide checksum is to be calculated from the
addition of 2-byte-wide values over the address range 0x0 to 0x7fd, starting with an offset of 0x0. The checksum is to
be stored at 0x7fe and 0x7ff in little endian format.
When executing Hexmate explicitly, use the option:
-ck=0-7fd@7fe+0g-2w-4
Adapt the following MPLAB XC8 code snippet for PIC devices, which calls ck_sub() and compares the runtime
checksum with that stored by Hexmate at compile time.
#include <stdint.h>
typedef uint16_t result_t; // size of fletcher result
result_t
fletcher8(const unsigned char * data, unsigned int n )
{
result_t sum = 0xff, sumB = 0xff;
unsigned char tlen;
while (n) {
tlen = n > 20 ? 20 : n;
n -= tlen;
do {
sumB += sum += *data++;
} while (--tlen);
sum = (sum & 0xff) + (sum >> 8);
sumB = (sumB & 0xff) + (sumB >> 8);
}
sum = (sum & 0xff) + (sum >> 8);
sumB = (sumB & 0xff) + (sumB >> 8);
return sumB << 8 | sum;
}
Here is how this function might be used when, for example, a 2-byte-wide Fletcher hash is to be calculated over the
address range 0x100 to 0x7fb, starting with an offset of 0x20. The checksum is to be stored at 0x7fc thru 0x7ff in little
endian format.
When executing Hexmate explicitly, use the following option. Note that the width cannot be controlled with the w
suboption, but the sign of this suboption's argument is used to indicate the required endianism of the result.
-ck=100-7bd@7fc+20g8w-4
This code can be called in a manner similar to that shown for the addition algorithms (see 7.2.3.1.1. Addition
Algorithms).
The code for the 2-byte-addition Fletcher algorithm, producing a 4-byte result is shown below.
#include <stdint.h>
typedef uint32_t result_t; // size of fletcher result
result_t
fletcher16(const unsigned int * data, unsigned n)
{
result_t sum = 0xffff, sumB = 0xffff;
unsigned tlen;
while (n) {
tlen = n > 359 ? 359 : n;
n -= tlen;
do {
sumB += sum += *data++;
} while (--tlen);
sum = (sum & 0xffff) + (sum >> 16);
sumB = (sumB & 0xffff) + (sumB >> 16);
}
sum = (sum & 0xffff) + (sum >> 16);
sumB = (sumB & 0xffff) + (sumB >> 16);
#include <stdint.h>
typedef uint16_t result_t; // size of CRC result
#define POLYNOMIAL 0x1021
#define WIDTH (8 * sizeof(result_t))
#define MSb ((result_t)1 << (WIDTH - 1))
result_t
crc(const unsigned char * data, unsigned n, result_t remainder) {
unsigned pos;
unsigned char bitp;
for (pos = 0; pos != n; pos++) {
remainder ^= ((result_t)data[pos] << (WIDTH - 8));
for (bitp = 8; bitp > 0; bitp--) {
if (remainder & MSb) {
remainder = (remainder << 1) ^ POLYNOMIAL;
} else {
remainder <<= 1;
}
}
}
return remainder;
}
The result_t type definition should be adjusted to suit the result width.
Here is how this function might be used when, for example, a 2-byte-wide CRC hash value is to be calculated values
over the address range 0x0 to 0xFF, starting with an initial value of 0xFFFF. The result is to be stored at 0x100 and
0x101 in little endian format.
When executing Hexmate explicitly, use the option:
-ck=0-ff@100+ffffg5w-2p1021
Adapt the following MPLAB XC8 code snippet for PIC devices, which calls crc() and compares the runtime hash
result with that stored by Hexmate at compile time.
}
// data verifies okay, continue with the program
The reflected CRC result can be calculated by reflecting the input data and final result, or by reflecting the
polynomial. The functions shown below can be customized to work with any result width (result_t). The
crc_reflected_IO() function calculates a reflected CRC hash value by reflecting the data stream bit positions.
Alternatively, the crc_reflected_poly() function does not adjust the data stream but reflects instead the
polynomial, which in both functions is specified by the POLYNOMIAL macro. Both functions use the reflect()
function to perform bit reflection.
#include <stdint.h>
typedef uint16_t result_t; // size of CRC result
typedef unsigned char read_t;
typedef unsigned int reflectWidth;
// This is the polynomial used by the CRC-16 algorithm we are using.
#define POLYNOMIAL 0x1021
#define WIDTH (8 * sizeof(result_t))
#define MSb ((result_t)1 << (WIDTH - 1))
#define LSb (1)
#define REFLECT_DATA(X) ((read_t) reflect((X), 8))
#define REFLECT_REMAINDER(X) (reflect((X), WIDTH))
reflectWidth
reflect(reflectWidth data, unsigned char nBits)
{
reflectWidth reflection = 0;
reflectWidth reflectMask = (reflectWidth)1 << nBits - 1;
unsigned char bitp;
for (bitp = 0; bitp != nBits; bitp++) {
if (data & 0x01) {
reflection |= reflectMask;
}
data >>= 1;
reflectMask >>= 1;
}
return reflection;
}
result_t
crc_reflected_IO(const unsigned char * data, unsigned n, result_t remainder) {
unsigned pos;
unsigned char reflected;
unsigned char bitp;
for (pos = 0; pos != n; pos++) {
reflected = REFLECT_DATA(data[pos]);
remainder ^= ((result_t)reflected << (WIDTH - 8));
for (bitp = 8; bitp > 0; bitp--) {
if (remainder & MSb) {
remainder = (remainder << 1) ^ POLYNOMIAL;
} else {
remainder <<= 1;
}
}
}
remainder = REFLECT_REMAINDER(remainder);
return remainder;
}
result_t
crc_reflected_poly(const unsigned char * data, unsigned n, result_t remainder) {
unsigned pos;
unsigned char bitp;
result_t rpoly;
rpoly = reflect(POLYNOMIAL, WIDTH);
for (pos = 0; pos != n; pos++) {
remainder ^= data[pos];
Here is how this function might be used when, for example, a 2-byte-wide reflected CRC result is to be calculated
over the address range 0x0 to 0xFF, starting with an initial value of 0xFFFF. The result is to be stored at 0x100 and
0x101 in little endian format.
When executing Hexmate explicitly, instead use the following option, noting that the algorithm selected is negative 5
in this case.
-ck=0-ff@100+ffffg-5w-2p1021
In your project, call either the crc_reflected_IO() or crc_reflected_poly() functions, as shown previously.
(110) too many file arguments; usage: cpp [input [output]] (Preprocessor)
CPP should be invoked with at most two file arguments. Contact Microchip Technical Support if the preprocessor is
being executed by a compiler driver.
(116) end of file within preprocessor macro argument from line * (Preprocessor)
A macro argument has not been terminated. This probably means the closing parenthesis has been omitted from a
macro invocation. The line number given is the line where the macro argument started, for example:
#define FUNC(a, b) func(a+b)
FUNC(5, 6; /* oops -- where is the closing bracket? */
(140) can’t open * file “*”: * (Driver, Preprocessor, Code Generator, Assembler)
The command file specified could not be opened for reading. Confirm the spelling and path of the file specified on the
command line, for example:
xc8 @communds
xc8 @commands
(165) #include filename “*” does not match actual name (check upper/lower case)
(Preprocessor)
In Windows versions this means the file to be included actually exists and is spelled the same way as the #include
filename; however, the case of each does not exactly match. For example, specifying #include “code.c” will
include Code.c, if it is found. In Linux versions this warning could occur if the file wasn’t found.
(167) too many values specified with -S option; “*” unused Preprocessor)
There were too many values supplied to the -S preprocessor option. See message 166.
If you need to stringize a token, you will need to define a special macro to do it, for example:
#define __mkstr__(x) #x
then use __mkstr__(token) wherever you need to convert token into a string.
Note that even if a structure only contains an int , for example, it cannot be assigned to an int variable and vice
versa.
*(int *)&c = 1
#pragma pack 2
Pragmas for all the standard printf-like function are already contained in <stdio.h>.
Either .. was meant to be an ellipsis symbol which would require you to add an extra dot, or it was meant to be a
structure member operator which would require you to remove one dot.
Note that variables with the same name, but defined with different scopes, are legal; but; not recommended.
If there is a switch statement before this default label, there could be one too many closing braces in the switch
code. That would prematurely terminate the switch statement. See message 246.
switch(input) {
case ’0’:
count++;
break;
case ’1’:
if(count>MAX)
count= 0;
} /* oops -- this shouldn’t be here */
break;
case ’2’: /* error flagged here */
If this was meant to be a structure with bit-fields, then the following illustrates an example:
struct {
unsigned first : 4; /* 4 bits wide */
Note: Omitting a semicolon from statements not preceding a close brace or keyword typically results in some other
error being issued for the following code which the parser assumes to be part of the original statement.
struct {
int a;
} my_struct;
(327) long long int argument required in printf-style format string (Parser)
A long long argument is required for this format specifier. Check the number and order of format specifiers and
corresponding arguments, for example:
printf("%llx", 2); // possibly you meant: printf("%llx", 2LL);
will perform a sign extension of the char variable to the longer type. If you do not want this to take place, use a cast,
for example:
ui = (unsigned char)sc;
If you do intend to use an expression like this, then indicate that this is so by a cast:
i = (int)dd;
If you do intend to use an expression like this, then indicate that this is so by a cast:
ip = (int *)i;
If you do intend to use an expression like this, indicate your intention by a cast:
i = (int)ip;
This is a common way of accessing bytes within a multi-byte variable. To indicate that this is the intended operation of
the program, use a cast:
This warning can also occur when converting between pointers to objects that have the same type, but which have
different qualifiers, for example:
char * cp;
/* yes, but what sort of characters? */
cp = "I am a string of characters";
If the default type for string literals is const char *, then this warning is quite valid. This should be written:
Omitting a qualifier from a pointer type is often disastrous and almost certainly not what you intend.
-GA/f0h+10
-SCODE=f000h
What is the delta value for this class? Possibly, you meant something like:
-DCODE=2
-ACODE=0h-1fffh
-ACODE=0h-1fffh
-ACODE=1fffh-3fffh
-AROM=1000h-1fffh
-ACODE=0h-ffffh
-AENTRY=0-0FFh-1FFh
-ACODE=0h-3fffh/a000h
-AENTRY=0-0FFhxfh
-pbss=f000h
-pbss=data+f000h
(454) link and load address can’t both be set to “.” in -P option (Linker)
The link and load address of a psect have both been specified with a dot character. Only one of these addresses can
be specified in this manner, for example:
-Pmypsect=1000h/.
-Pmypsect=./1000h
Both of these options are valid and equivalent. However, the following usage is ambiguous:
-Pmypsect=./.
(472) non-reentrant function “*” appears in multiple call graphs: rooted at “*” and “*”
(Linker)
This function can be called from both main-line code and interrupt code. Use the reentrant keyword, if this
compiler supports it, or recode to avoid using local variables or parameters, or duplicate the function, for example:
void interrupt my_isr(void)
{
scan(6); /* scan is called from an interrupt function */
}
void process(int a)
{
scan(a); /* scan is also called from main-line code */
}
(476) fixup overflow referencing * * (location 0x* (0x*+*), size *, value 0x*) (Linker)
The linker was asked to relocate (fixup) an item that would not fit back into the space after relocation. See the
following error message (1356) for more information.
(477) fixup overflow in expression (location 0x* (0x*+*), size *, value 0x*) (Linker)
The linker was asked to relocate (fixup) an item that would not fit back into the space after relocation. See the
following error message (1356) for more information.
(478) * range check failed (location 0x* (0x*+*), value 0x* > limit 0x*) (Linker)
This is an internal compiler error. Contact Microchip Technical Support with details.
The linker will issue this warning if the symbol (C or assembler) was defined multiple times in different modules. The
names of the modules are given in the error message. Note that C identifiers often have an underscore prepended to
their name after compilation.
(491) can’t find 0x* words for psect “*” in segment “*” (Linker)
One of the main tasks the linker performs is positioning the blocks (or psects) of code and data that is generated from
the program into the memory available for the target device. This error indicates that the linker was unable to find an
area of free memory large enough to accommodate one of the psects. The error message indicates the name of the
psect that the linker was attempting to position and the segment name which is typically the name of a class which is
defined by a -A linker option issued by the compiler driver. Typically psect names which are, or include, text relate
to program code. Names such as bss or data refer to variable blocks. This error can be due to two reasons.
First, the size of the program or the program’s data has exceeded the total amount of space on the selected device.
In other words, some part of your device’s memory has completely filled. If this is the case, then the size of the
specified psect must be reduced.
The second cause of this message is when the total amount of memory needed by the psect being positioned
is sufficient, but that this memory is fragmented in such a way that the largest contiguous block is too small to
accommodate the psect. The linker is unable to split psects in this situation. That is, the linker cannot place part of a
psect at one location and part somewhere else. Thus, the linker must be able to find a contiguous block of memory
large enough for every psect. If this is the cause of the error, then the psect must be split into smaller psects if
possible.
To find out what memory is still available, generate and look in the map file. Search for the string UNUSED
ADDRESS RANGES. Under this heading, look for the name of the segment specified in the error message. If the
name is not present, then all the memory available for this psect has been allocated. If it is present, there will be one
address range specified under this segment for each free block of memory. Determine the size of each block and
compare this with the number of words specified in the error message.
Psects containing code can be reduced by using all the compiler’s optimizations, or restructuring the program. If a
code psect must be split into two or more small psects, this requires splitting a function into two or more smaller
functions (which can call each other). These functions can need to be placed in new modules.
Psects containing data can be reduced when invoking the compiler optimizations, but the effect is less dramatic. The
program can need to be rewritten so that it needs less variables. If the default linker options must be changed, this
can be done indirectly through the driver using the driver -Wl, option. If a data psect cannot be positioned, then you
typically need to reduce the total size of variables being used.
For example, after receiving the message:
Can’t find 0x34 words (0x34 withtotal) for psect text in segment CODE (error)
In the CODE segment, there is 0x1c (0x25f-0x244+1) bytes of space available in one block and 0x30 available in
another block. Neither of these are large enough to accommodate the psect text which is 0x34 bytes long. Notice
that the total amount of memory available is larger than 0x34 bytes. If the function that is encoded into the text
psect can be split into two smaller functions, there is a chance the program will link correctly.
-Ptext=10f0h
(525) too many address (memory) spaces; space (*) ignored (Linker)
The limit to the number of address spaces (specified with the PSECT assembler directive) is currently 16.
(526) psect “*” not specified in -P option (first appears in “*”) (Linker)
This psect was not specified in a -P or -A option to the linker. It has been linked at the end of the program, which is
probably not where you wanted it.
(593) can’t find 0x* words (0x* withtotal) for psect “*” in segment “*” (Linker)
See message (491).
(629) bad storage class “*” in SDB file “*” line * column * (Cromwell)
This is an internal compiler error. Contact Microchip Technical Support with details.
(630) invalid syntax for prefix list in SDB file “*” (Cromwell)
This is an internal compiler error. Contact Microchip Technical Support with details.
(631) syntax error at token “*” in SDB file “*” line * column * (Cromwell)
This is an internal compiler error. Contact Microchip Technical Support with details.
(668) prefix list did not match any SDB types (Cromwell)
This is an internal compiler error. Contact Microchip Technical Support with details.
(669) prefix list matched more than one SDB type (Cromwell)
This is an internal compiler error. Contact Microchip Technical Support with details.
(691) interrupt functions not implemented for 12 bit PIC MCU (Code Generator)
The 12-bit (Baseline) range of PIC MCU processors do not support interrupts.
(692) more than one interrupt level is associated with the interrupt function “*”
(Code Generator)
Only one interrupt level can be associated with an interrupt function. Check to ensure that only one
interrupt_level pragma has been used with the function specified. This pragma can be used more than once on
main-line functions that are called from interrupt functions. For example:
#pragma interrupt_level 0
#pragma interrupt_level 1 /* oops -- which is it to be: 0 or 1? */
void interrupt isr(void)
{
(693) 0 (default) or 1 are the only acceptable interrupt levels for this function
(Code Generator)
The only possible interrupt levels are 0 or 1. Check to ensure that all interrupt_level pragmas use these levels.
#pragma interrupt_level 2 /* oops -- only 0 or 1 */
void interrupt isr(void)
{
/* isr code goes here */
}
break;
}
where fn1 is calling fn3 , and two arguments are evaluated by calling fn2 , which in turn calls fn3. The program
structure should be modified to prevent this type of call sequence.
(746) object “*” qualified const but not initialized (Code Generator)
An object has been qualified as const, but there is no initial value supplied at the definition. As this object cannot be
written by the C program, this can imply the initial value was accidentally omitted.
(748) variable “*” possibly used before being assigned a value (Code Generator)
This variable has possibly been used before it was assigned a value. Because it is an auto variable, this will result in
it having an unpredictable value, for example:
int main(void)
{
int a;
if(a) /* oops -- ’a’ has never been assigned a value */
process();
}
As a signed 8-bit quantity, c can only be assigned values -128 to 127. The constant is equal to 255 and is outside this
range. If you mean to set all bits in this variable, then use either of:
c = ~0x0;
c = -1;
which sets all the bits in the variable, regardless of variable size and without warning.
This warning can also be triggered by intermediate values overflowing. For example:
A quick check with your calculator reveals that 240 * 137 is 32880 which can easily be stored in an unsigned int,
but a warning is produced. Why? Because 240 and 137 and both signed int values. Therefore the result of the
multiplication must also be a signed int value, but a signed int cannot hold the value 32880. Both operands
are constant values so the code generator can evaluate this expression at compile time, but it must do so following all
the ANSI C rules. The following code forces the multiplication to be performed with an unsigned result:
{
int a, b;
a = 5;
/* this can never be false; always perform the true statement */
if(a == 5)
b = 6;
{
int a, b;
/* this loop must iterate at least once */
for(a=0; a!=10; a++)
b = func(a);
In this case the code generator can again pick up that a is assigned the value 0, then immediately checked to see
if it is equal to 10. Because a is modified during the for loop, the comparison code cannot be removed, but the code
generator will adjust the code so that the comparison is not performed on the first pass of the loop; only on the
subsequent passes. This cannot reduce code size, but it will speed program execution.
(758) constant conditional branch: possible use of “=” instead of “==” (Code Generator)
There is an expression inside an if or other conditional construct, where a constant is being assigned to a variable.
This can mean you have inadvertently used an assignment = instead of a compare ==, for example:
int a, b;
/* this can never be false; always perform the true statement */
if(a = 4)
b = 6;
will assign the value 4 to a, then , as the value of the assignment is always true, the comparison can be omitted and
the assignment to b always made. Did you mean:
Some devices require that special function register need to be read to clear hardware flags. To accommodate this,
in some instances the code generator does produce code for a statement which only consists of a variable ID. This
can happen for variables which are qualified as volatile. Typically the output code will read the variable, but not do
anything with the value read.
will always be true, because an unsigned value can never be less than zero.
will always be true, because an 8 bit signed char has a maximum negative value of -128.
(777) can’t allocate space for opnd structure within object “*” (offs: *) (Assembler)
The assembler has run out of memory.
psect my_text,local,class=CODE,with=basecode
which will define a psect called my_text and place this in the same page as the psect basecode.
(825) too many RAMBANK lines in chipinfo file for “*” (Assembler)
The chipinfo file contains a device section with too many RAMBANK fields. Reduce the number of values.
(827) too many COMMON lines in chipinfo file for “*” (Assembler)
There are too many lines specifying common (access bank) memory in the chip configuration file.
ENDM
getval EQU 55h ; oops -- choose a different name to the macro
The linker will issue this warning if the symbol (C or assembler) was defined multiple times in different modules. The
names of the modules are given in the error message. Note that C identifiers often have an underscore prepended to
their name after compilation.
(848) label defined in this module has also been declared EXTRN (Assembler)
The definition for an assembly label and an EXTRN declaration for the same symbol, appear in the same module. Use
GLOBAL instead of EXTRN if you want this symbol to be accessible from other modules.
(857) use of both local and global psect flags is illegal with same psect (Linker)
A local psect cannot have the same name as a global psect, for example:
psect text,class=CODE ; the text psect is implicitly global
MOVE r0, r1
; elsewhere:
psect text,local,class=CODE
MOVE r2, r4
The global flag is the default for a psect if its scope is not explicitly stated.
(864) argument to “size” psect flag must specify a positive constant (Assembler)
The parameter to the PSECT assembler directive’s size flag must be a positive constant number, for example:
PSECT text,class=CODE,size=-200 ; a negative size?
(866) argument to “reloc” psect flag must specify a positive constant (Assembler)
The parameter to the PSECT assembler directive’s reloc flag must be a positive constant number, for example:
psect test,class=CODE,reloc=-4 ; the reloc must be positive
(868) argument to “delta” psect flag must specify a positive constant (Assembler)
The parameter to the PSECT assembler directive’s DELTA flag must be a positive constant number, for example:
PSECT text,class=CODE,delta=-2 ; negative delta value doesn’t make sense
(870) argument to “pad” psect flag must specify a positive constant (Assembler)
The parameter to the PSECT assembler directive’s PAD flag must be a non-zero positive integer.
(871) argument to “space” psect flag must specify a positive constant (Assembler)
The parameter to the PSECT assembler directive’s space flag must be a positive constant number, for example:
PSECT text,class=CODE,space=-1 ; space values start at zero
Look for other psect definitions that specify a different class name.
(884) please ensure you have write permissions to the configuration file (Driver)
The compiler was not successfully setup using the --setup driver option because the driver was unable to access
the XML configuration file. Ensure that you have write permission to this file. The driver will search the following
configuration files in order:
• the file specified by the environment variable XC_XML
• the file /etc/xc.xml if the directory ’/etc ’ is writable and there is no .xc.xml file in your home directory
• the file .xc.xml file in your home directory
If none of the files can be located, then the above error will occur.
(895) can’t request and specify options in the one command (Driver)
The usage of the driver options --getoption and --setoption is mutually exclusive.
(899) can’t open option file “*” for application “*”: * (Driver)
An option file specified by a --getoption or --setoption driver option could not be opened. If you are using
the --setoption option, ensure that the name of the file is spelled correctly and that it exists. If you are using the
--getoption option ensure that this file can be created at the given location or that it is not in use by any other
application.
(902) no chip name specified; use “* –CHIPINFO” to see available chip names (Driver)
The driver was invoked without selecting what chip to build for. Running the driver with the –CHIPINFO option will
display a list of all chips that could be selected to build for.
(907) unknown memory space tag “*” in “*” option specification (Driver)
A parameter to this memory option was a string but did not match any valid tags. Refer to the section of this manual
that describes this option to see what tags (if any) are valid for this device.
(913) “*” option can cause compiler errors in some standard header files (Driver)
Using this option will invalidate some of the qualifiers used in the standard header files, resulting in errors. This issue
and its solution are detailed in the section of this manual that specifically discusses this option.
(915) no room for arguments (Preprocessor, Parser, Code Generator, Linker, Objtohex)
The code generator could not allocate any more memory.
(951) start of fill range must be less than end of range (Hexmate)
The -FILL option has been given a range where the start is greater than the end. The parameters can be incomplete
or entered in the wrong order.
(965) -STRPACK option not yet implemented; option will be ignored (Hexmate)
This option currently is not available and will be ignored.
(972) only modifiers “h” and “l” valid with this format (Parser)
Only modifiers h (short) and l (long) are legal with this printf format specifier.
(994) some command-line options are disabled and compilation is delayed (Driver)
The compiler is operating in demo mode. Some command-line options are disabled, the compilation speed will be
slower.
(995) some command-line options are disabled; code size is limited to 16kB, compilation is delayed (Driver)
The compiler is operating in demo mode. Some command-line options are disabled; the compilation speed will be
slower, and the maximum allowed code size is limited to 16 KB.
(1016) missing argument* to “*” specification in chipinfo file “*” at line * (Driver)
This value of this attribute is blank in the chip configuration file.
(1017) extraneous argument* to “*” specification in chipinfo file “*” at line * (Driver)
There are too many attributes for the listed specification in the chip configuration file.
(1018) illegal number of “*” specification* (* found; * expected) in chipinfo file “*” at line *
(Driver)
This attribute was expected to appear a certain number of times; but it did not appear for this chip.
(1021) syntax error reading “*” value in chipinfo file “*” at line * (Driver)
The chip configuration file incorrectly defines the specified value for this device. If you are modifying this file yourself,
take care and refer to the comments at the beginning of this file for a description on what type of values are expected
here.
(1022) syntax error reading “*” range in chipinfo file “*” at line * (Driver)
The chip configuration file incorrectly defines the specified range for this device. If you are modifying this file yourself,
take care and refer to the comments at the beginning of this file for a description on what type of values are expected
here.
(1032) use –HELP=<option> for usage of these command line options (Hexmate)
More detailed information is available for a specific option by passing that option to the -HELP option.
(1088) function pointer “*” is used but never assigned a value (Code Generator)
A function call involving a function pointer was made, but the pointer was never assigned a target address, for
example:
void (*fp)(int);
fp(23); /* oops -- what function does fp point to? */
(1098) conflicting declarations for variable “*” (*:*) (Parser, Code Generator)
Differing type information has been detected in the declarations for a variable, or between a declaration and the
definition of a variable, for example:
extern long int test;
int test; /* oops -- which is right? int or long int ? */
(1178) the “*” option has been removed and has no effect (Driver)
This option no longer exists in this version of the compiler and has been ignored. Use the compiler’s --help option
or refer to the manual to find a replacement option.
(1179) interrupt level for function “*” cannot exceed * (Code Generator)
The interrupt level for the function specified is too high. Each interrupt function is assigned a unique interrupt
level. This level is considered when analyzing the call graph and reentrantly called functions. If using the
interrupt_level pragma, check the value specified.
(1190) FAE license only - not for use in commercial applications (Driver)
Indicates that this compiler has been activated with an FAE license. This license does not permit the product to be
used for the development of commercial applications.
(1205) using the configuration file *; you can override this with the environment variable HTC_XML (Driver)
This is the compiler configuration file selected during compiler setup. This can be changed via the HTC_XML
environment variable. This file is used to determine where the compiler has been installed.
(1207) some of the command line options you are using are now obsolete (Driver)
Some of the command line options passed to the driver have now been discontinued in this version of the compiler;
however, during a grace period these old options will still be processed by the driver.
(1208) use –help option or refer to the user manual for option details (Driver)
An obsolete option was detected. Use --help or refer to the manual to find a replacement option that will not result
in this advisory message.
(1210) Visit the Microchip website (www.microchip.com) for a possible upgrade (Driver)
Visit our website to see if an upgrade is available to address the issue(s) listed in the previous compiler message.
Navigate to the MPLAB XC8 C Compiler page and look for a version upgrade downloadable file. If your version is
current, contact Microchip Technical Support for further information.
(1248) symbol (*) encountered with undefined type size (Code Generator)
The code generator was asked to position a variable, but the size of the variable is not known. This is an internal
compiler error. Contact Microchip Technical Support with details.
(1250) could not find space (* byte*) for variable * (Code Generator)
The code generator could not find space in the banked RAM for the variable specified.
(1254) could not find space (* byte*) for data block (Code Generator)
The code generator could not find space in RAM for the data psect that holds initialized variables.
(1257) local variable “*” is used but never given a value (Code Generator)
An auto variable has been defined and used in an expression, but it has not been assigned a value in the C code
before its first use. Auto variables are not cleared on startup and their initial value is undefined. For example:
int main(void) {
double src, out;
out = sin(src); /* oops -- what value was in src? */
(1258) possible stack overflow when calling function “*” (Code Generator)
The call tree analysis by the code generator indicates that the hardware stack can overflow. This should be treated
as a guide only. Interrupts, the assembler optimizer and the program structure can affect the stack usage. The stack
usage is based on the C program and does not include any call tree derived from assembly code.
(1284) malformed mapfile while generating summary: CLASS expected but not found
(Driver)
The map file being read to produce a memory summary is malformed. Either the file has been edited or corrupted, or
this is a compiler error – contact Microchip Technical Support with details.
(1286) malformed mapfile while generating summary: no link address at position * ( Driver)
The map file being read to produce a memory summary is malformed. Either the file has been edited or corrupted, or
this is a compiler error – contact Microchip Technical Support with details.
(1289) line range limit exceeded, possibly affecting ability to debug code (Cromwell)
A C statement has produced assembly code output whose length exceeds a preset limit. This means that debug
information produced by CROMWELL may not be accurate. This warning does not indicate any potential code failure.
(1293) couldn’t find type for “*” in DWARF debugging information entry (Cromwell)
The type of symbol could not be determined from the SDB file passed to CROMWELL. Either the file has been edited
or corrupted, or this is a compiler error – contact Microchip Technical Support with details.
(1294) there is only one day left until this license expires (Driver)
The compiler is running as a demo and will be unable to run in PRO mode after the evaluation license has expired in
less than one day’s time. After expiration, the compiler can be operated in Free mode indefinitely, but will produce a
larger output binary.
(1295) there are * days left until this license will expire (Driver)
The compiler is running as a demo and will be unable to run in PRO mode after the evaluation license has expired in
the indicated time. After expiration, the compiler can be operated in Free mode indefinitely, but will produce a larger
output binary.
(1300) maximum number of program classes reached; some classes may be excluded from debugging
information (Cromwell)
CROMWELL is passed a list of class names on the command line. If the number of class names passed in is too
large, not all will be used and there is the possibility that debugging information will be inaccurate.
(1302) could not find valid ELF output extension for this device (Cromwell)
The extension could not be for the target device family.
(1310) specified speed (*Hz) exceeds max operating frequency (*Hz); defaulting to *Hz
(Driver)
The frequency specified to the perform suboption to --RUNTIME option is too large for the selected device.
--RUNTIME=default,speed:0xffffffff
(1311) missing configuration setting for config word *; using default (Driver)
The configuration settings for the indicated word have not be supplied in the source code and a default value will be
used.
(1312) conflicting runtime perform sub-option and configuration word settings; assuming *Hz (Driver)
The configuration settings and the value specified with the perform suboption of the --RUNTIME options conflict and
a default frequency has been selected.
(1343) hexfile data at address 0x* (0x*) overwritten with 0x* (Objtohex)
The indicated address is about to be overwritten by additional data. This would indicate more than one section of
code contributing to the same address.
(1346) can’t find 0x* words for psect “*” in segment “*” (largest unused contiguous range 0x%lX) (Linker)
See also message (491). The new form of message also indicates the largest free block that the linker could find.
Unless there is a single space large enough to accommodate the psect, the linker will issue this message. Often
when there is banking or paging involved the largest free space is much smaller than the total amount of space
remaining,
(1347) can’t find 0x* words (0x* withtotal) for psect “*” in segment “*” (largest unused contiguous range
0x%lX) (Linker)
See also message (593). The new form of message also indicates the largest free block that the linker could find.
Unless there is a single space large enough to accommodate the psect, the linker will issue this message. Often
when there is banking or paging involved the largest free space is much smaller than the total amount of space
remaining,
(1349) initialization of absolute variable "*" in RAM is not supported (Code Generator)
An absolute variable, one defined using __at(address), cannot be assigned an initial value when it is defined.
Place an assignment to the variable at an appropriate location in your program.
int foobar __at(0x20) = 0x55; /* oops --
you cannot assign a value to an absolute variable */
(1350) pointer operands to “-” must reference the same array (Code Generator)
If two addresses are subtracted, the addresses must be of the same object to be ANSI compliant.
int * ip;
int fred, buf[20];
ip = &buf[0] - &fred; /* oops --
second operand must be an address of a "buf" element */
(1356) fixup overflow referencing * * (0x*) into * byte* at 0x*/0x* -> 0x* (*** */0x*) (Linker)
’Fixup’ is the process conducted by the linker of replacing symbolic references to operands with an absolute value.
This takes place after positioning the psects (program sections or blocks) into the available memory. ‘Fixup overflow’
is when a symbol’s value is too large to fit within the assembler instruction. For example, if an assembler instruction
has an 8-bit field to hold an address and the linker determines that the symbol used to represent this address has the
value 0x110, then clearly this value cannot be encoded into the instruction.
Fixup errors are often caused by hand-written assembly code. Common mistakes that trigger these errors include
failing to mask a full, banked data address in file register instructions, or failing to mask the destination address in
jump or call instructions. If this error is triggered by assembly code generated from C source, then it is often that
constructs like switch() statements have generated a block of assembly too large for jump instructions to span.
Adjusting the default linker options can also causes such errors.
To identify these errors, follow these steps.
• Perform a debug build (in MPLAB X IDE select Debug > Discrete Debugger Operation > Build for
Debugging; alternatively, on the command line use the
-D__DEBUG option).
• Open the relevant assembler list file (ensure the MPLAB X IDE project properties has XC8 Compiler >
Preprocessing and Messaging > Generate the ASM listing file enabled; alternatively, on the command line,
use the -Wa,-a option).
• Find the instruction at the address quoted in the error message.
Consider the following error message.
The file being linked was main.obj. This tells you the assembly list file in which you should be looking is main.lst.
The location of the instruction at fault is 0x7FF0 (You can also tell from this message that the instruction is expecting
a 1 byte quantity—this size is rounded to the nearest byte—but the value was determined to be 0x100).
In the assembly list file, search for the address specified in the error message.
and to confirm, look for the symbol referenced in the assembler instruction at this address in the symbol table at the
bottom of the same file.
In this example, the hand-written PIC18 movwf instruction causing the problem takes an 8-bit offset into a bank of
memory, but clearly the address 0x100 exceeds this size. The instruction should have been written as:
MOVWF BANKMASK(_foo)
which masks out the top bits of the address containing the bank information. Alternatively, the linker can be instructed
to ignore fixup overflows, or to issue a warning rather than an error in such situations. See 6.1.31. Fixupoverflow
Linker Option for more information, as the use of this option may compromise the detection of genuine errors.
If the assembler instruction that caused this error was generated by the compiler, in the assembler list file look back
up the file from the instruction at fault to determine which C statement has generated this instruction. You will then
need to examine the C code for possible errors.
(1357) fixup overflow storing 0x* in * byte* at 0x*/0x* -> 0x* (*** */0x*) (Linker)
See message (1356).
(1371) float type can’t be bigger than double type; double has been changed to * bits
(Driver)
Use of the -fshort-double options has result in the size of the double type being smaller than that of the float
type. This is not permitted by the C Standard. The double type size has been increased to be that indicated.
(1375) multiple interrupt functions (* and *) defined for device with only one interrupt vector (Code Generator)
The named functions have both been qualified interrupt, but the target device only supports one interrupt vector and
hence one interrupt function.
interrupt void isr_lo(void) {
// ...
}
interrupt void isr_hi(void) { // oops, cannot define two ISRs
// ...
}
(1376) initial value (*) too large for bitfield width (*) (Code Generator)
A structure with bit-fields has been defined an initialized with values. The value indicated it too large to fit in the
corresponding bit-field width.
struct {
unsigned flag :1;
unsigned mode :3;
} foobar = { 1, 100 }; // oops, 100 is too large for a 3 bit object
(1386) unable to determine the semantics of the configuration setting “*” for register “*”
(Parser, Code Generator)
The numerical value supplied to a configuration bit setting has no direct association setting specified in the data
sheet. The compiler will attempt to honor your request, but check your device data sheet.
#pragma config OSC=11
// oops -- there is no direct association for that value on an 18F2520
// either use OSC=3 or OSC=RC
(1389) attempt to reprogram configuration * “*” with * (is *) (Parser, Code Generator)
A Configuration bit that was already programmed has been programmed again with a conflicting setting to the
original.
#pragma config WDT=ON
#pragma config WDT=OFF // oops -- watchdog on or off?
(1391) constant object size of * exceeds the maximum of * for this chip (Code Generator)
The const object defined is too large for the target device.
const int array[200] = { ... }; // oops -- not on a Baseline part!
(1392) function “*” is called indirectly from both mainline and interrupt code
(Code Generator)
A function has been called by main-line (non-interrupt) and interrupt code. If this warning is issued, it highlights that
such code currently violates a compiler limitation for the selected device.
(1394) attempting to create memory range ( * - * ) larger than page size * (Driver)
The compiler driver has detected that the memory settings include a program memory “page” that is larger than the
page size for the device. This would mostly likely be the case if the --ROM option is used to change the default
memory settings. Consult your device data sheet to determine the page size of the device you are using and to
ensure that any contiguous memory range you specify using the --ROM option has a boundary that corresponds to
the device page boundaries.
--ROM=100-1fff
The above might need to be paged. If the page size is 800h, the above could specified as
--ROM=100-7ff,800-fff,1000-17ff,1800-1fff
(1395) notable code sequence candidate suitable for compiler validation suite detected (*)
(Code Generator)
The compiler has in-built checks that can determine if combinations of internal code templates have been
encountered. Where unique combinations are uncovered when compiling code, this message is issued. This
message is not an error or warning and its presence does not indicate possible code failure, but if you are willing to
participate, the code you are compiling can be sent to Support to assist with the compiler testing process.
(1396) “*” positioned in the * memory region (0x* - 0x*) reserved by the compiler
(Code Generator)
Some memory regions are reserved for use by the compiler. These regions are not normally used to allocate
variables defined in your code. However, by making variables absolute, it is possible to place variables in these
regions and avoid errors that would normally be issued by the linker. Absolute variables can be placed at any
location, even on top of other objects. This warning from the code generator indicates that an absolute has been
detected that will be located at memory that the compiler will be reserving. You must locate the absolute variable at a
different location. This message will commonly be issued when placing variables in the common memory space.
char shared __at(0x7); // oops, this memory is required by the compiler
(1397) unable to implement non-stack call to “*”; possible hardware stack overflow
(Code Generator)
The compiler must encode a C function call without using a call assembly instruction and the hardware stack (i.e.,
use a lookup table), but is unable to. A call instruction might be required if the function is called indirectly via a
pointer, but if the hardware stack is already full, an additional call will cause a stack overflow.
(1401) eeprom qualified variables can’t be accessed from both interrupt and mainline code (Code Generator)
All eeprom variables are accessed via routines that are not reentrant. Code might fail if an attempt is made to
access eeprom-qualified variables from interrupt and main-line code. Avoid accessing eeprom variables in interrupt
functions.
(1402) a pointer to eeprom can’t also point to other data types (Code Generator)
A pointer cannot have targets in both the EEPROM space and ordinary data space.
(1410) can’t assign the result of an invalid function pointer (Code Generator)
The compiler allows some functions to be called via a constant cast to be a function pointer, but not all. The address
specified is not valid for this device.
foobar += ((int (*)(int))0x0)(77);
// oops -- you cannot call a function with a NULL pointer
(1413) pointer comparisons involving address of “*”, positioned at address 0x0, may be invalid (Code
Generator)
An absolute object placed at address 0 has had its address taken. By definition, this is a NULL pointer and code
which checks for NULL (i.e., checks to see if the address is valid) can fail.
int foobar __at(0x00);
int * ip;
int main(void)
{
ip = &foobar; // oops -- 0 is not a valid address
(1418) Attempt to read “control” qualified object which is Write-Only (Code Generator)
An attempt was made to read a write-only register.
state = OPTION; // oops -- you cannot read this register
(1419) using the configuration file *; you can override this with the environment variable XC_XML (Driver)
This is the compiler configuration file that is selected during compiler setup. This can be changed via the XC_XML
environment variable. This file is used to determine where the compiler has been installed. See message 1205.
(1425) __pack qualifier only applies to structures and structure members (Parser)
The qualifier you have specified only makes sense when used with structures or structure members. It will be
ignored.
__pack int c; // oops -- there aren’t inter-member spaces to pack in an int
(1426) 24-bit floating point types are not supported; * have been changed to 32-bits
(Driver)
Floating-point types must be 32-bits wide to conform to the CCI Standard. These types will be compiled as 32-bit
wide quantities.
-fshort-double=24
Remove the path information and use the -I option to indicate this, for example:
#include <lcd.h>
(1429) attribute “*” is not understood by the compiler; this attribute will be ignored
(Parser)
The indicated attribute you have used is not valid with this implementation. It will be ignored.
int x __attribute__ ((deprecate)) = 0;
(1431) the __section specifier is applicable only to variable and function definitions at file-scope (Parser)
You cannot attempt to locate local objects using the __section() specifier.
int main(void) {
int __section("myData") counter; // oops -- you cannot specify a section for autos
(1435) variable “*” is incompatible with other objects in section “*” (Code Generator)
You cannot place variables that have differing startup initializations into the same psect. That is, variables that are
cleared at startup and variables that are assigned an initial non-zero value must be in different psects. Similarly, bit
objects cannot be mixed with byte objects, like char or int.
int __section("myData") input; // okay
int __section("myData") output; // okay
int __section("myData") lvl = 0x12; // oops -- not with uninitialized
bit __section("myData") mode; // oops again -- no bits with bytes
// each different object to their own new section
(1436) “*” is not a valid nibble; use hexadecimal digits only (Parser)
When using __IDLOC(), the argument must only consist of hexadecimal digits with no radix specifiers or other
characters. Any character which is not a hexadecimal digit will be programmed as a 0 in the corresponding location.
__IDLOC(0x51); // oops -- you cannot use the 0x radix modifier
(1441) use __at() instead of '@' and ensure the address is applicable (Parser)
You have used the @ address specifier when using the IAR C extensions. Any address specified is unlikely to be
correct on a new architecture. Review the address in conjunction with your device data sheet. To prevent this warning
from appearing again, use the reviewed address with the __at() specifier instead.
(1452) one or more spaces are defined as data and code (Cromwell)
The options passed to Cromwell indicate memory space is both in the code and data space. Unless you are explicitly
running this application, consider this an internal error. Contact Microchip Technical Support with details.
--code-space=1,2 --data-space=1
(1453) stack size specified for non-existent or unused * software stack (Driver)
The -mstack option has been used, specifying a maximum size for some or all of the available stacks, but the
compiler cannot see that the indicated stack has been used by the program. For example, space might have been
requested for an interrupt stack, but there was no corresponding interrupt function found in the code.
-mstack=reentrant:20:20:auto
Oops, you have asked for two interrupt stacks, but the compiler cannot see both interrupt function definitions.
(1454) stack size specified (*) is greater than available (*) (Driver)
The -mstack option has been used to specify the maximum sizes for each stack, but the total amount of memory
requested exceeds the amount of memory available.
-mstack=software:1000:1000:20000
Oops, too many sizes for a device with only one interrupt.
(1460) function-level profiling is not available for the selected chip (Driver)
Function profiling is only available for PIC18 or enhanced mid-range devices. If you are not using such a device, do
not attempt to use function profiling.
(1462) reentrant data stack model option conflicts with stack management option and will be ignored (Code
Generator)
The managed stack option allows conversion of function calls that would exceed the hardware stack depth to calls
that will use a lookup table. This option cannot be enabled if the reentrant function model is also enabled. If you
attempt to use both the managed stack and reentrant function model options, this message will be generated. Code
will be compiled with the stack management option disabled. Either disable the reentrant function model or the
managed stack option.
(1463) reentrant data stack model not supported on this device; using compiled stack for data (Code
Generator)
The target device does not support reentrant functions. The program will be compiled so that stack-based data is
placed on a compiled stack.
(1464) number of arguments passed to function “*” does not match function's prototype
(Code Generator)
A function was called with arguments, but the declaration of the function had an empty parameter list (as opposed to
a parameter list of void).
int test(); // oops--this should define the parameters
...
test(12, input);
(1465) the stack frame size for function “*” (* bytes) has exceeded the maximum allowable (* bytes) (Code
Generator)
The compiler has been able to determine that the software stack requirements for the named function’s auto,
parameter, and temporary variables exceed the maximum allowable. The limits are 31 for enhanced mid-range
devices and 127 for PIC18 devices. Reduce the size or number of these variables. Consider static local objects
instead of auto objects.
reentrant int addOffset(int offset) {
int report[400]; // oops--this will never fit on the software stack
(1466) registers * unavailable for code generation of this expression (Code Generator)
The compiler has been unable to generate code for this statement. This is essentially a “can’t generate code” error
message (message 712), but the reason for this inability to compile relates to there not being enough registers
available. See message 712 for suggested workarounds.
(1467) pointer used for writes includes read-only target “*” (Code Generator)
A pointer to a non-const-qualified type is being used to write a value, but the compiler knows that this pointer has
targets (the first of which is indicated) that have been qualified const. This could lead to code failure or other error
messages being generated.
void keepTotal(char * cp) {
*cp += total;
}
char c;
const char name[] = "blender";
keepTotal(&c);
keepTotal(&name[2]); // oops--will write a read-only object
(1469) function specifier “reentrant/software” used with “*” ignored (Code Generator)
The reentrant (or software) specifier was used with a function (indicated) that cannot be encoded to use the
software stack. The specifier will be ignored and the function will use the compiled stack.
reentrant int main(void) // oops--main cannot be reentrant
{ ...
(1471) indirect function call via a NULL pointer ignored (Code Generator)
The compiler has detected a function pointer with no valid target other than NULL. That pointer has been used to call
a function. The call will not be made.
int (*fp)(int, int);
result = fp(8,10); // oops--this pointer has not been initialized
(1474) read-only target “*” may be indirectly written via pointer (Code Generator)
This is the same as message 1467, but for situations where an error is required. The compiler has encountered a
pointer that is used to write, and one or more of the pointer’s targets are read-only.
const char c = ‘x’;
char * cp = &c; // will produce warning 359 about address assignment
*cp = 0x44; // oops--you ignored the warning above, now you are
// actually going to write using the pointer?
(1478) initial value for “*” differs to that in *:* (Code Generator)
The named object has been defined more than once and its initial values do not agree. Remember that uninitialized
objects of static storage duration are implicitly initialized with the value zero (for all object elements or members,
where appropriate).
char myArray[5] = { 0 };
// elsewhere
char myArray[5] = {0,2,4,6,8}; // oops--previously initialized
// with zeros, now with different values
(1480) initial value(s) not supplied in braces; zero assumed (Code Generator)
The assignment operator was used to indicate that the object was to be initialized, but no values were found in the
braces. The object will be initialized with the value(s) 0.
int xy_map[3][3] = { }; // oops--did you mean to supply values?
(1481) call from non-reentrant function, “*”, to “*” might corrupt parameters
(Code Generator)
If several functions can be called indirectly by the same function pointer, they are called ‘buddy’ functions, and the
parameters to buddy functions are aligned in memory. This allows the parameters to be loaded without knowing
exactly which function was called by the pointer (as is often the case). However, this means that the buddy functions
cannot directly or indirectly call each other.
(1484) the branch errata option is turned on and a BRW instruction was detected
(Assembler)
The use of this instruction may cause code failure with the selected device. Check the published errata for your
device to see if this restriction is applicable for your device revision. If so, remove this instruction from hand-written
assembly code.
btfsc status,2
brw next ;oops--this instruction cannot be safely used
call update
(1485) * mode is not available with the current license and other modes are not permitted by the
NOFALLBACK option (Driver)
This compiler’s license does not allow the requested compiler operating mode. Since the --nofallback option is
enabled, the compiler has produced this error and will not fall back to a lower operating mode. If you believe that you
are entitled to use the compiler in the requested mode, this error indicates that your compiler might not be activated
correctly.
(1486) size of pointer cannot be determined during preprocessing. Using default size *
(Preprocessor)
The preprocessor cannot determine the size of pointer type. Do not use the sizeof operator in expressions that
need to be evaluated by the preprocessor.
#if sizeof(int *) == 3 // oops - you can't take the size of a pointer type
#define MAX 40
#endif
(1488) the stack frame size for function “*” may have exceeded the maximum allowable (* bytes) (Code
Generator)
This message is emitted in the situation where the indicated function's software-stack data has exceeded the
theoretical maximum allowable size. Data outside this stack space will only be accessible by some instructions that
could attempt to access it. In some situations the excess data can be retrieved, your code will work as expected, and
you can ignore this warning. This is likely if the function calls a reentrant function that returns a large object, like a
structure, on the stack. At other times, instructions that are unable to access this data will, in addition to this warning,
trigger an error message at the assembly stage of the build process, and you will need to look at reducing the amount
of stack data defined by the function.
(1491) runtime sub-option “*” is not available for this device (Driver)
A specified suboption to the --RUNTIME option is not available for the selected device.
xc8 --CHIP=MCP19114 --RUNTIME=+osccal main.c
(1492) using updated 32-bit floating-point libraries; improved accuracy might increase code size (Code
Generator)
This advisory message ensures you are aware of the changes in 32-bit floating-point library code operation that might
lead to an increase in code size.
(1493) updated 32-bit floating-point routines might trigger “can't find space” messages appearing after
updating to this release; consider using the smaller 24-bit floating-point types (Linker)
This advisory message ensures you are aware of the changes in 32-bit floating-point library code operation, which
might lead to the Can’t Find Space error message that has been issued.
(1504) the PIC18 extended instruction set was enabled but is not supported by this compiler (Parser)
The MPLAB XC8 compiler does not support generation of code using the PIC18 extended instruction set. The
extended instruction set configuration bit must always be disabled.
#pragma config XINST=ON // oops--this must be disabled at all times
(1506) multiple interrupt functions (* and *) defined at interrupt level * (Code Generator)
More than one interrupt function has been defined for the same priority.
void interrupt low_priority
isr(void)
{ ... }
void interrupt low_priority // oops--you can have two ISRs
loisr(void) // with the same priority
{ ... }
(1507) asmopt state popped when there was no pushed state (Assembler)
The state of the assembler optimizers was popped in assembly code but there was no corresponding push.
movlw 20h
movwf LATB
opt asmopt_pop; oops--there was never a state pushed
(1510) non-reentrant function “*” appears in multiple call graphs and has been duplicated by the compiler
(Code Generator)
This message indicates that the generated output for a function has been duplicated since it has been called from
both main-line and interrupt code. It does not indicate a potential code failure. If you do not want function output
duplicated, consider using the hybrid stack model (if possible), or restructure your source code.
(1512) stable/invariant mode optimizations no longer implemented; specifier will be ignored (Code
Generator)
This specifier is no longer available and has been ignored.
(1513) target “*” of pointer “*” not in the memory space specified by * (Code Generator)
The pointer assigned an address by this statement was defined using a pointer-target specifier. This assignment
might be assigning addresses to the pointer that conflict with that memory space specifier.
__rom int * ip;
int foobar;
ip = &foobar; // oops -- foobar is in data memory, not program memory
(1515) disabling OCG optimizations for this device is not permitted (Driver)
Due to memory limits, projects targeting some devices cannot be built. Ensure that the OCG category of optimization
is enabled.
(1516) compiler does not support 64-bit integers on the target architecture
Due to memory restrictions, the current device cannot support 64-bit integers and a smaller integer will be used
instead. Choose a type smaller than long long to suppress this warning.
long long int result; // oops - this will not be 64-bits wide
(1518) * function call made with an incomplete prototype (*) (Code Generator)
A function has been called with the compiler not having seen a complete prototype for that function. Check for an
empty parameter list in the declaration.
void foo(); // oops -- how will this call be encoded?
int main(void)
{
foo();
}
1521 internal error encountered creating DWARF information; contact Microchip support with details
(Cromwell)
This is an internal compiler error. Contact Microchip Technical Support with details.
1523 debug_source state popped when there was no pushed state (Assembler)
The state of the debug_source setting was popped but no previous value had been pushed.
DEBUG_SOURCE asm
MY_UNLOCK_MACRO
DEBUG_SOURCE pop ; oops - there was no prior push of the debug source state
1525 selected language standard or device does not support a memory heap (Driver)
A heap has been specified on a device that does not support dynamic memory allocation, or the C90 language
specification was selected with this option. Dynamic memory allocation is only supported with PIC18 or Enhanced
Mid-range devices, and only when building with the C99 language standard.
xc8-cc -mcpu=12f509 -mheap=0x100 main.c
1526 total software stack(s) and memory heap size specified (* bytes) is greater than available (* bytes)
(Driver)
The size of the memory requested for the software stack and the heap exceeds the amount of data memory available
on the selected device.
xc8-cc -mcpu=18f4520 main.c -mheap=1000 -mstack=reentrant:4000
Oops, that device does not implement 5000 bytes of data memory.
1527 auto-sized software stack(s) and/or memory heap will share in * byte(s) of memory (Driver)
After allocation of static objects, the compiled stack, and any software stacks and/or heap that have a fixed size
requested in the -mstack/-mheap options, any free memory is then divided up for those software stacks and/or
heap that have used an auto size specification. If the amount of memory available (as indicated in the message) is
very small, this warning indicates that use of the software stack/heap features might be restricted.
1528 no memory can be allocated to software stack(s) and/or memory heap (Driver)
The compiler was unable to allocate memory to any of the software stacks and/or heap.
1529 the -msmart-io-format option has no effect with the currently selected language standard and will be
ignored (Driver)
The -msmart-io-format option can only be specified when using the C99 language standard, which has full
support for smart IO functions.
xc8-cc -mcpu=18f4520 main.c -std=c90 -msmart-io-format=fmt="%d%c"
Oops, you cannot use the -msmart-io-format with the C90 language standard.
1602 contents of the hex-data (*) do not conform with the chosen output type (*) (Hexmate)
There is data to be written to the HEX file that is not valid for the particular HEX file format chosen, for example, data
might be at an address too large for the supported format. Consider a different output format or check the source of
the offending data.
1604 Storage Area Flash has been enabled by the configuration bits; ensure this memory is not used for
program code (Assembler)
A configuration bit setting has enabled the storage area flash memory on this device. This memory should not be
used by any other part of the program, so it will need to be reserved using an option (e.g. -mreserve). Check your
device data sheet for more information.
#pragma config SAFEN=ON ;make sure ordinary program code does not use this space
1605 Block Table Read Protection has been enabled by the configuration bits; this may affect variable
initialization and reading constants in program memory (Assembler)
A configuration bit setting has enabled the block table read protection feature. This can affect any code that reads
from program memory, resulting in code failing. Check your device data sheet for more information.
#pragma config EBTRB=ON ;remember this might affect reading program memory
(2011) __interrupt attribute/specifier has a base (*) not supported by this device (Parser)
The address specified with the base() argument to the __interrupt() specifier is not valid for the target device.
It cannot, for example, be lower than the reset value of the IVTBASE register.
//oops -- the base() address is too low
(2013) argument “*” used by “*” attribute/specifier not supported by this device (Parser)
The argument of the indicated specifier is not valid for the target device.
// oops -- base() can’t be used with a device that does not
(2014) interrupt vector table @ 0x* already has a default ISR “*” (Code Generator)
You can indicate only one default interrupt function for any vector location not specified in a vector table. If you have
specified this twice, check to make sure that you have specified the correct base() address for each default.
void __interrupt(irq(default), base(0x100)) tc0Int(void) { ...
(2015) interrupt vector table @ 0x* already has an ISR (*) to service IRQ * (*)
(Parser or Code Generator)
You have specified more than one interrupt function to handle a particular interrupt source in the same vector table.
void __interrupt(irq(TMR0), base(0x100)) tc0Int(void) { ...
(2016) interrupt function “*” does not service any interrupt sources (Code Generator)
You have defined an interrupt function but did not indicate which interrupt source this function should service. Use the
irq() argument to indicate the source or sources.
//oops -- what interrupt does this service?
(2017) config programming has disabled multi-vectors, “irq” in __interrupt attribute/specifier is ignored
(Code Generator)
An interrupt function has used the irq() argument to specify an interrupt source, but the vector table has
been disabled via the configuration bits. Either re-enable vectored interrupts or use the priority keyword in the
__interrupt() specifier to indicate the interrupt source.
#pragma config MVECEN=0
// oops -- you cannot disable the vector table then allocate interrupt
(2018) interrupt vector table @ 0x* has multiple functions (* and *) defined at interrupt level * (Code
Generator)
The program for a device operating in legacy mode has specified a vector table that contains more than one function
at the same interrupt priority-level in the same table. In this mode, there can be at most one interrupt function for
each priority level in each vector table.
#pragma config MVECEN=0
(2020) IRQ * (*) in vector table @ 0x* is unassigned, will be programmed with the address of a * (Code
Generator)
The interrupt vector in the indicated vector table has not been programmed with an address. The compiler will
program this vector with an address as specified by the -mundefints option.
(2022) runtime sub-option “ivt” specifies a base address (0x*) not supported by this device (Driver)
The address specified with the ivt sub-option is not valid for the selected target device. It cannot, for example, be
lower than the reset value of the IVTBASE register.
(2024) runtime sub-option “ivt” specifies an interrupt table (@ 0x*) that has not been defined (Driver)
The ivt sub-option to the --RUNTIME option was used to specify a IVT address, but this address has not been
specified in the source code with any ISR. Check that the address in the option is correct, or check that the base()
arguments to the __interrupt() specifier are specified and are correct.
--RUNTIME=+ivt:0x100
Oops -- is this the right address? Nothing in the source code uses this base address.
(2025) qualifier * on local variable “*” is not allowed and has been ignored (Parser)
Some qualifiers are not permitted with auto or local static variables. This message indicates that the indicated
qualifier has been ignored with the named variable.
near int foobar; // oops -- auto variables cannot use near
(2026) variables qualified “*” are not supported for this device (Parser)
Some variable qualifiers are not permitted with some devices.
eeprom int serialNo; // oops -- can’t use eeprom with PIC18 devices
(2028) external declaration for identifier “*” doesn't indicate storage location
(Code Generator)
The declaration for an external object (e.g., one defined in assembly code) has no storage specifiers to indicate the
memory space in which it might reside. Code produced by the compiler which accesses it might fail. Use const or a
bank specifier as required.
extern int tapCounter; // oops - how does the compiler access this?
(2029) a function pointer cannot be used to hold the address of data (Parser)
A function pointer must only hold the addresses of function, not variables or objects.
int (*fp)(int);
int foobar;
fp = &foobar; // oops - a variable’s address cannot be assigned
(2030) a data pointer cannot be used to hold the address of a function (Parser)
A data pointer (even a generic void * pointer) cannot be used to hold the address of a function.
void *gp;
int myFunc(int);
gp = foobar; // oops - a function’s address cannot be assigned
(2033) recursively called function might clobber a static register it has allocated in expression (Code
Generator)
The compiler has encountered a situation where a register is used by an expression that is defined in a function that
is called recursively and that expression is part of a larger expression that requires this same function to be called.
The register might be overwritten and the code may fail.
unsigned long fib_rec(unsigned long n)
{
// the temporary result of the LHS call to fib_rec() might
// store the result in a temp that is clobbered during the RHS
// call to the same function
return ((n > 1) ? (fib_rec(n-1) + fib_rec(n-2)) : n);
}
(2034) 24-bit floating-point types are not CCI compliant; use 32-bit setting for compliance
(Parser)
The CCI does not permit the use of 24-bit floating point types. If you require compliance, use the -no-short-float
and -no-short-double options, which will ensure the IEEE standard 32-bit floating-point type is used for float
and double types.
(2035) use of sizeof() in preprocessor expressions is deprecated; use __SIZEOF_*__ macro to avoid this
warning (Preprocessor)
The use of sizeof() in expressions that must be evaluated by the preprocess are no longer supported.
Preprocessor macros defined by the compiler, such as __SIZEOF_INT__, can be used instead. This does not
affect the C operator sizeof() which can be used in the usual way.
#if (sizeof(int) > 2) // oops -- use (__SIZEOF_INT__ > 2) instead
(2036) use of @ is not compliant with CCI, use __at() instead (Parser)
The CCI does not permit the definition of absolute functions and objects that use the @ address construct. Instead,
place __at(address) after the identifier in the definition.
int foobar @ 0x100; // oops -- use __at(0x100) instead
(2037) short long integer types are not compliant with CCI (Parser)
The CCI does not permit use of the 3-byte short long type. Instead consider an equivalent long int type.
short long input; // oops -- consider input to be long when using CCI
(2038) use of short long integer types is deprecated; use __int24 or __uint24 to avoid this warning (Parser)
The short long type specifiers has been replaced with the more portable __int24 (replacing short long) and
__uint24 (replacing unsigned short long) types.
short long input; // oops -- use __int24 as the type for input
(2042) no target device specified; use the -mcpu option to specify a target device
(Driver)
The driver was invoked without selecting what chip to build for. Running the driver with the -mprint-devices
option will display a list of all chips that could be selected to build for.
xc8-cc main.c
Oops, use the -mcpu option to specify the device to build for.
Oops, the device name must be exactly one of those shown by -mprint-devices.
(2046) identifier length must be between * and *; using default length * (Driver)
The number of characters specified as the largest significant identifier length is illegal and the default length of 255
has been used.
-N=16
(2047) 24-bit floating point types are not supported when compiling in C99 (Driver)
The float and double types must be 32-bits wide when compiling for the C99 Standard. If you need 24-bit floating-
point types, then you might be able to select the C90 compliant libraries (using the -mc90lib option) or you must
compile for C90.
xc8-cc -mcpu=18f4520 -fshort-double main.c
(2048) C language extension “*” is not supported and will be ignored (Driver)
The indicated language extension is not supported.
xc8-cc -mcpu=16f1937 -mext=iar main.c
(2049) C99 compliant libraries are currently not available for baseline or mid-range devices, or for enhanced
mid-range devices using a reentrant stack; using C90 libraries (Driver)
At present, C99-compliant libraries are not available for all devices. The C90-compliant libraries can be used with
these device while still building your source code to the C99 standard. Alternatively, you may choose to build to the
C90 standard.
(2050) use of the -mcci option is deprecated; use -mext=cci to avoid this warning (Driver)
Always use the -mext=cci option to select the Common C Interface.
(2051) The current license does not permit the selected optimization level* (Driver)
This compiler’s license does not allow the requested compiler operating mode.
xc8-cc -mcpu=18f4520 -Os main.c
Oops, you cannot select level 's' optimizations if this compiler is unlicensed.
(2052) The current license does not permit the selected optimization level and other levels are not permitted
by the NOFALLBACK option (Driver)
This compiler’s license does not allow the requested compiler operating mode. Since the --nofallback option is
enabled, the compiler has produced this error and will not fall back to a lower optimization level. If you believe that
you are entitled to use the requested optimizations, this error might indicate that your compiler is not be activated
correctly.
(2054) the language standard “*” is not supported; using C99 (Driver)
The language standard specified by the -std option is not supported by the compiler. The compiler will use the C99
standard instead.
xc8-cc -mcpu=12f510 -std=c11 main.c
(2056) use of the -fmode option is deprecated; use -O to control optimizations and avoid this warning (Driver)
The compiler no longer uses both the mode and optimization selection to fully specify which optimizations are
performed. All optimizations are now controllable via the optimization level, which is selectable using the compiler’s
-O option. Unlicensed compilers, however, cannot use all levels.
(2057) The XC8 compiler installation appears to be corrupted. Please reinstall and try again (Driver)
The compiler has detected that something about the installation is not valid. This is most like due to compiler
applications being deleted or moved.
(2058) function "*" cannot be inlined with code coverage enabled (Code Generator)
With the code coverage feature enabled, functions cannot be inlined. This advisary is just reminding you that the
indicated function will not be inlined while code coverage is still in effect.
(2059) conflicting * register values found in Start Segment Address record (3) (Hexmate)
Hexmate will pass through any type 3 records in the Hex files being processed, but if there is any conflict in the
values specified for the CS or IP registers in these records, it will flag this error.
(2061) word width required when specifying reserve byte order hash (Hexmate)
If you are calculating a CRC reading data words in the Hex file in reverse order, you must specify a word width in
bytes with Hexmate's r suboption to -CK. If you are using the assembler driver, this is specified using the revword
suboption to -mchecksum.
(2062) word width must be * when specifying reserve byte order hash (Hexmate)
If you are calculating a CRC reading data words in the Hex file in reverse order, the word width can only be one of
the values indicated in the message. This value is specified with Hexmate's r suboption to -CK. If you are using the
assembler driver, this is specified using the revword suboption to -mchecksum.
(2063) * address must be a multiple of the word width when performing a reverse byte order hash (Hexmate)
If you are calculating a CRC reading data words in the Hex file in reverse order, the starting and ending addresses
must be multiples of the word width specified in Hexmate's -CK option or the assembler's -mchecksum option.
(2064) PIC18 extended instruction cannot be used when the standard instruction set is selected (Assembler)
PIC18 assembly projects must be set up to use one of the standard or extended instructions sets. This message will
be displayed if you have used an extended instruction without having enabled the extended instruction set using the
-misa option.
(2068) use of the opt control "*" is deprecated; use the corresponding directive (Assembler)
The assembler controls of the form OPT CONTROL should no longer be used. Equivalent directives are available and
can be formed by removing the OPT token from the control. Instead of using OPT TITLE "My great project",
for example, use TITLE "My great project".
(2069) use of the radix option of the list control is deprecated; use the radix directive (Assembler)
The LIST assembler control previously allowed the input source to be specified using the r argument to the LIST
option. This should no longer be used. Use the RADIX directive instead. Instead of using OPT LIST r=hex, for
example, use RADIX hex.
(2070) device specified by the PROCESSOR directive conflicts with that set by the -mcpu option (Assembler)
The -mcpu driver option sets the target device being built for. The PROCESSOR directive may be used, if required,
to ensure that an assembly source file is only ever built for the specified device. If there is a mismatch in the device
specified by the option and the directive, this message will be displayed.
(2071) could not find record containing hash starting address 0x* (Hexmate)
Hexmate was asked to calculate a hash from data starting at an address that did not appear in the HEX file.
(2072) only SHA256 is currently supported (set width control to 256) (Hexmate)
The width suboption can only be set to 256 or -256 when selecting a SHA hash algorithm. Alternatively, the width
suboption can be omitted entirely.
(2073) when compiling for C90, specifying an output file for dependencies is not supported and will be
ignored (Driver)
Only the Clang front end can create a file containing dependencies.
(2074) word size for byte skip with hash calculation must be * (Hexmate)
The argument to the s suboption of -CK, which indicates the size of the word in which bytes will be skipped or the
purposes of calculating a hash value is not permitted.
(2075) word size required when requesting byte skip with hash calculation (Hexmate)
An argument to the s suboption of -CK is required. It represents the word width in which bytes will be skipped for the
purposes of calculating a hash value.
(2076) number of bytes for byte skip with hash calculation must be * (Hexmate)
The number of bytes to skip within each word is illegal.
Oops, the number of bytes to skip must be less than 4, the skip word width, for example s4.2.
(2077) number of bytes required when requesting byte skip with hash calculation (Hexmate)
An argument following the . in the s suboption of -CK is required. It represents the number of bytes to skip in each
word for the purposes of calculating a hash value.
Oops, a number is required after the . in the s argument, for example s4.2.
(2078) the number of hash bytes to which the trailing code is appended (*) must be no greater than the hash
width (*) (Hexmate)
A trailing code has been requested to follow the specified number of bytes of the hash value, but this number is larger
than that the entire hash.
Oops, if the hash value is only 2 bytes long, asking for a trailing code to be appended after every 4 bytes makes no
sense. Instead try t00.1, for example, to append the code to each byte.
(2079) the hash width (*) must be a multiple of the number of hash bytes appended with a trailing code (*)
(Hexmate)
A trailing code has been requested to follow the specified number of bytes of the hash value, but this number is not a
multiple of the hash width.
Oops, if the hash value is 4 bytes long, asking for a trailing code to be appended after every 3 bytes makes no sense.
Instead try t00.2, for example, to append the code to every two bytes of the hash.
WARN "I have not yet confirmed that this is the correct threshold"
movlw 22
movwf threshold,c
(2081) the device architecture "*" does not match previously encountered object files "*" (Linker)
The linker was passed objects files that were built for different target devices. This is only likely to occur if you
are using precompiled object files or libraries built from assembler code. Ensure all modules are built for the same
device.
(2083) the current license does not permit the "*" feature (Driver)
A feature has been used that is not permitted by the compiler license. A PRO compiler license is required for some
compiler features. Ensure that your compiler is installed correctly and has not expired if you believe that you have the
appropriate license.
Oops, the stack guidance feature, for example, requires a PRO compiler license to operate.
(2084) absolute object "*" has an address that lies within memory utilized by the compiler and will likely lead
to code failure (Code Generator)
An absolute object (one declared using __at()) has been placed at an address that must be used by the compiler.
The object will likely be corrupted by compiler generated code at runtime and lead to program failure.
(2085) the BANKISEL directive has no effect with the currently selected device and will be ignored
(Assembler)
The BANKISEL assembler directive is required only for Baseline and Mid-range devices. It will be ignored for other
devices, but check your device data sheet to ensure your code that performs indirect access of objects is valid for the
selected device.
BANKISEL myVar ;oops - this device does not use separate indirect access bank
bits
movwf INDF
(2086) memory for a heap has been reserved in response to the detection of calls to malloc/calloc/realloc/free
function(s) (Driver)
The compiler has detected calls to the standard dynamic memory allocation functions when the auto size value was
set with the -mheap option. A compiler-determined amount of memory has been reserved for the heap.
(2087) memory for the * software stack has been reserved in response to the detection of functions built for
reentrancy (Driver)
The compiler has detected functions built with the reentrant (software stack) model when the auto size value was set
with the -mstack option. A compiler-determined amount of memory has been reserved for the indicated stack.
(2088) fixup overflow referencing * * (0x*) into * byte* at 0x*/0x* -> 0x* (*** */0x*) (Linker)
This is the warning variant of message 1356, which might be issued if using the --fixupoverflow=warn linker
option. See error message 1356 for more information.
(2089) fixup overflow storing 0x* in * byte* at 0x*/0x* -> 0x* (*** */0x*) (Linker)
This is the warning variant of message 1357, which might be issued if using the --fixupoverflow=warn linker
option. See error message 1356 for more information.
(2091) fixup overflow messages have been recorded in the list file "*" (Linker)
The lstwarn argument to the --fixupoverflow was specified and fixup overflow situations were detected in the
program. This advisory message is a reminder to check the assembly list file to see where fixup overflows were
detected.
(2092) relocatable list file is not available; fixup overflow list file messages cannot be generated (Linker)
The lstwarn argument to the --fixupoverflow was specified and fixup overflow situations were detected in the
program, but the linker is not processing any assembly list file, so the warning messages cannot be printed. The
linker completes the information in the assembly list file produced by the assembler after the link step is complete.
Check to ensure that a list file was requested, and that you have not explicitly used the linker's --norlf option.
(2093) number of arguments passed to function "*" does not match function's prototype (Code Generator)
This is the error variant of message 1464. A function was called with arguments, but the declaration of the function
had an empty parameter list (as opposed to a parameter list of void).
int test(); // oops--this should define the parameters
...
test(12, input);
The error form of this message is printed if the function in question is not externally defined.
(2094) The selected Device Family Pack (DFP) contains features not implemented in this compiler version;
consider using an alternate DFP or a more recent compiler release (Driver, Code Generator, Assembler)
The compiler has detected features in the DFP which it does not implement. This is mostly likely the result of
selecting a DFP that is much more recent than the compiler. Choose an older DFP or a newer version of the compiler
with the same DFP.
Customer Support
Users of Microchip products can receive assistance through several channels:
• Distributor or Representative
• Local Sales Office
• Embedded Solutions Engineer (ESE)
• Technical Support
Customers should contact their distributor, representative or ESE for support. Local sales offices are also available to
help customers. A listing of sales offices and locations is included in this document.
Technical support is available through the website at: www.microchip.com/support
Legal Notice
Information contained in this publication regarding device applications and the like is provided only for your
convenience and may be superseded by updates. It is your responsibility to ensure that your application meets with
Trademarks
The Microchip name and logo, the Microchip logo, Adaptec, AnyRate, AVR, AVR logo, AVR Freaks, BesTime,
BitCloud, chipKIT, chipKIT logo, CryptoMemory, CryptoRF, dsPIC, FlashFlex, flexPWR, HELDO, IGLOO, JukeBlox,
KeeLoq, Kleer, LANCheck, LinkMD, maXStylus, maXTouch, MediaLB, megaAVR, Microsemi, Microsemi logo,
MOST, MOST logo, MPLAB, OptoLyzer, PackeTime, PIC, picoPower, PICSTART, PIC32 logo, PolarFire, Prochip
Designer, QTouch, SAM-BA, SenGenuity, SpyNIC, SST, SST Logo, SuperFlash, Symmetricom, SyncServer,
Tachyon, TempTrackr, TimeSource, tinyAVR, UNI/O, Vectron, and XMEGA are registered trademarks of Microchip
Technology Incorporated in the U.S.A. and other countries.
APT, ClockWorks, The Embedded Control Solutions Company, EtherSynch, FlashTec, Hyper Speed Control,
HyperLight Load, IntelliMOS, Libero, motorBench, mTouch, Powermite 3, Precision Edge, ProASIC, ProASIC Plus,
ProASIC Plus logo, Quiet-Wire, SmartFusion, SyncWorld, Temux, TimeCesium, TimeHub, TimePictra, TimeProvider,
Vite, WinPath, and ZL are registered trademarks of Microchip Technology Incorporated in the U.S.A.
Adjacent Key Suppression, AKS, Analog-for-the-Digital Age, Any Capacitor, AnyIn, AnyOut, BlueSky,
BodyCom, CodeGuard, CryptoAuthentication, CryptoAutomotive, CryptoCompanion, CryptoController, dsPICDEM,
dsPICDEM.net, Dynamic Average Matching, DAM, ECAN, EtherGREEN, In-Circuit Serial Programming, ICSP,
INICnet, Inter-Chip Connectivity, JitterBlocker, KleerNet, KleerNet logo, memBrain, Mindi, MiWi, MPASM,
MPF, MPLAB Certified logo, MPLIB, MPLINK, MultiTRAK, NetDetach, Omniscient Code Generation, PICDEM,
PICDEM.net, PICkit, PICtail, PowerSmart, PureSilicon, QMatrix, REAL ICE, Ripple Blocker, SAM-ICE, Serial
Quad I/O, SMART-I.S., SQI, SuperSwitcher, SuperSwitcher II, Total Endurance, TSHARC, USBCheck, VariSense,
ViewSpan, WiperLock, Wireless DNA, and ZENA are trademarks of Microchip Technology Incorporated in the U.S.A.
and other countries.
SQTP is a service mark of Microchip Technology Incorporated in the U.S.A.
The Adaptec logo, Frequency on Demand, Silicon Storage Technology, and Symmcom are registered trademarks of
Microchip Technology Inc. in other countries.
GestIC is a registered trademark of Microchip Technology Germany II GmbH & Co. KG, a subsidiary of Microchip
Technology Inc., in other countries.
All other trademarks mentioned herein are property of their respective companies.
© 2022, Microchip Technology Incorporated, Printed in the U.S.A., All Rights Reserved.
ISBN: 978-1-6683-0484-6