The common approach is to make a const array that contains the appropriate values (initial SP, initial PC = adress of init code, addresses of the interrupt service routines) and use some compiler-dependant magic to force the linker to place this array at address 0.
An example in gcc (from my http://www.voti.nl/bmptk):
void (* const __vectors[ 8 ])(void)
__attribute__ ((section(".vectors"))) = {
(void (*)(void)) & __stack_end,
__startup,
// interrupt verctors etc.
};
The __ attribute__ ((section(".vectors"))) marks this array as part of a section called "vectors". The matching linkerscript ensures that that section is placed first in the flash memory:
MEMORY
{
rom (rx) : org = ROM_START, len = ROM_SIZE
ram (rwx) : org = RAM_START, len = RAM_SIZE
nul (rwx) : org = 0x20000000, len = 0k
}
. . .
SECTIONS
{
.text :
{
. = ALIGN(4);
KEEP(*(.vectors));
. . .
# other sections come here (= the rest of your code)
In normal situations this is something that your tool vendor/builder/creator has done for you.