Next: Linker Scripts, Up: Libraries [Contents]
To make a program that has been compiled with GCC to run, you need to write some startup code. The initial piece of startup code is called a crt0. (C RunTime 0) This is usually written in assembler, and it’s object gets linked in first, and bootstraps the rest of the application when executed. This file needs to do the following things.
If you plan to burn your code in a ROM, then the crt0 typically has to do all the hardware initialization that is required to run an application. This can include things like initializing serial ports or run a memory check. It all depends on the hardware.
When there is a ROM monitor present, usually a user trap can be called and then the ROM takes over. Pick a safe vector with no side effects. Some ROMs have a builtin trap handler just for this case.
portable between all the m68k based boards we have here. Example Crt0.S.
/* ANSI concatenation macros. */ #define CONCAT1(a, b) CONCAT2(a, b) #define CONCAT2(a, b) a ## b
These we’ll use later.
/* These are predefined by new versions of GNU cpp. */ #ifndef __USER_LABEL_PREFIX__ #define __USER_LABEL_PREFIX__ _ #endif /* Use the right prefix for global labels. */ #define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
These macros are to make this code portable between both COFF and a.out. COFF always has an _ (underline) prepended on the front of all global symbol names. a.out has none.
#ifndef __REGISTER_PREFIX__ #define __REGISTER_PREFIX__ #endif /* Use the right prefix for registers. */ #define REG(x) CONCAT1 (__REGISTER_PREFIX__, x) #define d0 REG (d0) #define d1 REG (d1) #define d2 REG (d2) #define d3 REG (d3) #define d4 REG (d4) #define d5 REG (d5) #define d6 REG (d6) #define d7 REG (d7) #define a0 REG (a0) #define a1 REG (a1) #define a2 REG (a2) #define a3 REG (a3) #define a4 REG (a4) #define a5 REG (a5) #define a6 REG (a6) #define fp REG (fp) #define sp REG (sp)
This is for portability between assemblers. Some register names have a % or $ prepended to the register name.
/* * Set up some room for a stack. We just grab a chunk of memory. */ .set stack_size, 0x2000 .comm SYM (stack), stack_size
Set up space for the stack. This can also be done in the linker script, but it typically gets done here.
/* * Define an empty environment. */ .data .align 2 SYM (environ): .long 0
Set up an empty space for the environment. This is bogus on any most ROM monitor, but we setup a valid address for it, and pass it to main. At least that way if an application checks for it, it won’t crash.
.align 2 .text .global SYM (stack) .global SYM (main) .global SYM (exit) /* * This really should be __bss_start, not SYM (__bss_start). */ .global __bss_start
Setup a few global symbols that get used elsewhere. __bss_start needs to be unchanged, as it’s setup by the linker script.
/* * start -- set things up so the application will run. */ SYM (start): link a6, #-8 moveal #SYM (stack) + stack_size, sp /* * zerobss -- zero out the bss section */ moveal #__bss_start, a0 moveal #SYM (end), a1 1: movel #0, (a0) leal 4(a0), a0 cmpal a0, a1 bne 1b
The global symbol start
is used by the linker as the default
address to use for the .text
section. then it zeros the
.bss
section so the uninitialized data will all be cleared. Some
programs have wild side effects from having the .bss section let
uncleared. Particularly it causes problems with some implementations of
malloc
.
/* * Call the main routine from the application to get it going. * main (argc, argv, environ) * We pass argv as a pointer to NULL. */ pea 0 pea SYM (environ) pea sp@(4) pea 0 jsr SYM (main) movel d0, sp@-
Setup the environment pointer and jump to main()
. When
main()
returns, it drops down to the exit
routine below.
/* * _exit -- Exit from the application. Normally we cause a user trap * to return to the ROM monitor for another run. */ SYM (exit): trap #0
Implementing exit
here is easy. Both the rom68k
and bug
can handle a user caused exception of zero
with no side effects.
Although the bug
monitor has a user caused trap that will return
control to the ROM monitor, this solution has been more portable.
Next: Linker Scripts, Up: Libraries [Contents]