You can assign global variables to specific addresses with the global variable address modifier. These variables are called absolute variables. They are useful for accessing memory mapped I/O ports and have the following syntax:
Declaration = <TypeSpec> <Declarator> [@<Address>|@"<Section>"] [= <Initializer>];
where:
A segment is created for each global object specified with an absolute address. This address must not be inside any address range in the SECTIONS entries of the link parameter file. Otherwise, there would be a linker error (overlapping segments). If the specified address has a size greater than that used for addressing the default data page, pointers pointing to this global variable must be __far. An alternate way to assign global variables to specific addresses is setting the PLACEMENT section in the Linker parameter file (see the following listing).
#pragma DATA_SEG [__SHORT_SEG] <segment_name>
An older method of accomplishing this is shown in the following listing.
<segment_name> INTO READ_ONLY <Address> ;
The following listing is an example using correctly and incorrectly the global variable address modifier and the following listing is a possible PRM file that corresponds with the example Listing.
int glob @0x0500 = 10; // OK, global variable "glob" is // at 0x0500, initialized with 10 void g() @0x40c0; // error (the object is a function) void f() { int i @0x40cc; // error (the object is a local variable) }
/* the address 0x0500 of "glob" must not be in any address range of the SECTIONS entries */ SECTIONS MY_RAM = READ_WRITE 0x0800 TO 0x1BFF; MY_ROM = READ_ONLY 0x2000 TO 0xFEFF; MY_STACK = READ_WRITE 0x1C00 TO 0x1FFF; MY_IO_SEG = READ_WRITE 0x0400 TO 0x4ff; END PLACEMENT IO_SEG INTO MY_IO_SEG; DEFAULT_ROM INTO MY_ROM; DEFAULT_RAM INTO MY_RAM; SSTACK INTO MY_STACK; END