> I beg to differ on this. When writing very cycle concious assembly you often > have to make sure everything is aligned properly on page boundaries. For > example, I will often put all the state routines for a state machine on the > same 256-byte page, and have the state variable be the offset of the routine > for the current state on that page. Now going to the current state is as > simple as: > > movlw high(state_machine_state_0) > movwf pclath > movf current_state,W > movwf pcl Using the linker doesn't proclude this type of programming. In fact, I think it would make your allocation of routines to pages easier. This example has two contraints. First, you need a block of code (table) that starts on a 256 word boundary. Second, you need certain modules (the ones that contain the state routines) to be loaded onto the same program memory page as the table. If it makes sense to partition the code so that all the state routines end up in the same module, then the problem becomes trivial so I'll show how to do this assuming the state routines are in different modules. Here is the relevant section of my default linker control file for the 16F876: CODEPAGE NAME=config START=0x2007 END=0x2007 //special processor config word CODEPAGE NAME=code0 START=0 END=0x7FF //code page 0 CODEPAGE NAME=code1 START=0x800 END=0xFFF //code page 1 CODEPAGE NAME=code2 START=0x1000 END=0x17FF //code page 2 CODEPAGE NAME=code3 START=0x1800 END=0x1FFF //code page 3 DATABANK NAME=bank0 START=0x20 END=0x6F //register bank 0 DATABANK NAME=bank1 START=0xA0 END=0xEF //register bank 1 DATABANK NAME=bank2 START=0x110 END=0x16F //register bank 2 DATABANK NAME=bank3 START=0x190 END=0x1EF //register bank 3 SHAREBANK NAME=globalram START=0x70 END=0x7F PROTECTED //global regs, bank 0 SHAREBANK NAME=globalram START=0xF0 END=0xFF PROTECTED //global regs, bank 1 SHAREBANK NAME=globalram START=0x170 END=0x17F PROTECTED //global regs, bank 2 SHAREBANK NAME=globalram START=0x1F0 END=0x1FF PROTECTED //global regs, bank 3 SECTION NAME=.udata_shr RAM=globalram //global memory mapped to all register banks SECTION NAME=.BANK0 RAM=bank0 //for registers explicitly in bank 0 SECTION NAME=.BANK1 RAM=bank1 //for registers explicitly in bank 1 SECTION NAME=.BANK2 RAM=bank2 //for registers explicitly in bank 2 SECTION NAME=.BANK3 RAM=bank3 //for registers explicitly in bank 3 I can use this setup without modification for the vast majority of projects, including this example. Note that each code page is defined as a separate linker section. This prevents individual modules from straddling code pages, which guarantees you can do GOTOs and CALLs within a module without having to worry about PCLATH each time, assuming you aren't explicitly setting code sections or addresses. Let's pick page 1 to be the page that will hold the states jump table and all the state routines. To locate the table, just force it to start at any of the 256 word boundaries on that page. The linker will place code at fixed addresses first, then place relocatable code around it. I would stick the table right at the start of the page so that it introduces no additional memory fragmentation: code h'800' ;start of 256 word block on states page tbl_states goto state_0 goto state_1 ... goto state_49 Now you only have to make sure that sections of code that contain the state routines jumped to from the states table are also loaded into page 1: ; ; State routines. The STATE_xx labels are jumped to from the ; states table, and must be on the same page as the states table. ; code1 code ;force same page as states table state_0 blah blah state_1 blah blah I believe this now gets you everything you asked for. However, there are also some additional advantages. You only specify the modules or sections of code that must be on the states page, and the linker allocates everything else. You can (should) break up the code into separate modules. Each of these modules now gets its own name space for local symbols. As long as all the code you've specified to go onto the states page fits, there will be no problem. If it doesn't fit, you will get a linker error telling you so. It will not silently overflow to another page leaving you to figure out why things are broken at debug time. All in all the linker is a powerful tool that can be a big help if let it. You can think of it as a superset of absolute mode. You can still force fixed addresses when you want to, but you can let the linker allocate space in the majority of cases where you don't care. Even if you forced all addresses, it would still give you separate local name spaces for modules and detect memory collisions between your forced allocations. ******************************************************************** Olin Lathrop, embedded systems consultant in Littleton Massachusetts (978) 742-9014, olin@embedinc.com, http://www.embedinc.com -- http://www.piclist.com hint: The list server can filter out subtopics (like ads or off topics) for you. See http://www.piclist.com/#topics