here's an example i found in
Clemson University -- CPSC 231 -- Fall 2001				19

Non-stack variables

  global variable - a variable declared/defined in one source file that is
      available to routines in other source files

  external variable - a variable needed by but not defined in the current
      source file

  static variable - a local variable that must retain its value between
      procedure calls

  variable type		"global"  "static"  "automatic"  dynamic
			--------  --------  -----------  ------------------
  scope/visibility	 global    local      local      global or local
  lifetime		program   program    fn. call    from alloc to free

Program sections

  reflect different logical parts of program

    text - program code
    data - initialized variables
    bss (block started by symbol) - uninitialized variables
    stack - automatically allocated variables (local variables) and other stack
       frame entries
    heap - dynamically allocated variables

        | . . . |
        +-------+ -.			int x = 1;	/* x placed in data */
        | text  |   \			int y;		/* y in placed bss  */
        |-------|    | program's	int main(){
        | data  |    | layout in	   int z;	/* z alloc. on stack */
        |-------|    | memory		   ...
        | bss   |    |			   y = 2;	/* code put in text  */
        |-------|    |			   ...
        | heap  |    |			   return 0;	/* retval in reg %o0 */
        |---|---|    |			}
        | . V . |    |
        | . . . |    |			a dynamically allocated variable will
        | . ^ . |    |			  placed in the heap
        |---|---|    |
        | stack |   /			a local variable declared with the
        +-------+ -'			  keyword "static" in C will be placed
        | . . . |			  in data if initialized, else in bss

  different protection -- text is read-only; data, bss, the heap, and the stack
    are read-write; a special rodata section is read-only

  the assembler maintains a separate location counter for the first three
    program sections above (the stack and heap do not have to be declared
    in the assembly program)

  pseudo-ops can be used to switch back and forth among the sections in
    the source code, but the assembler will gather like kinds of regions
    into separate memory sections

  .section ".text" - assembler switches to the text section location counter
			(the assembler starts in text section by default)

  .section ".data" - assembler switches to the data section location counter
    .word  - followed by a list of initialized values
    .byte  - followed by a list of initialized values (an ASCII character
             code is recognized by a single character placed in double quotes)
    .ascii - character string in double quotes
    .asciz - null-terminated character string, useful for strings when using
             routines from the C library

  .section ".bss"  - assembler switches to the bss section location counter
    .skip  - advances location counter a given number of bytes

  .section ".rodata" - read-only initialized data section

  .align  - variables of word size must be aligned (.align 4)

  .global - allows symbol to be referenced beyond current source file (also,
            you need to declare a symbol global for gdb to be able to use it)


	int x = 1;
	int y;
	int main(){
	   int z;

	   printf( "variable x from data section has value %d\n", x );

	   y = 2;
	   printf( "variable y from bss section has value  %d\n", y );

	   z = 3;
	   printf( "local variable z has value             %d\n", z );

	   return 0;

		.global main
		save %sp,-104,%sp

	     /* load value from initialized non-stack variable "x" */
		set x,%o0
		ld  [%o0],%o1
		set fmt1,%o0
		call printf

	     /* place value into uninitialized non-stack variable "y" */
		mov 2,%o1
		set y,%o0
		st  %o1,[%o0]

	     /* load value from non-stack variable "y" */
		set y,%o0
		ld  [%o0],%o1
		set fmt2,%o0
		call printf

	     /* place value into local variable "z" on stack              */
	     /*   note that the address of "z" is not z but %fp-4 instead */
		mov 3,%o0
		st  %o0,[%fp-4]

	     /* load value from local variable "z" on stack               */
	     /*   note that the address of "z" is not z but %fp-4 instead */
		ld  [%fp-4],%o1
		set fmt3,%o0
		call printf

	     /* place return value in %i0 here, will be in %o0 for caller */
		clr  %i0


		.section ".data"
	x:	.word 1

		.section ".bss"
	y:	.skip 4

		.section ".rodata"
	fmt1:	.asciz "variable x from data section has value %d\n"
	fmt2:	.asciz "variable y from bss section has value  %d\n"
	fmt3:	.asciz "local variable z has value             %d\n"

in C++ programs, the library initializers (i.e., startup code) should run
  first, then application constructors, then the application program, then
  application destructors, and finally the library finalizers (exit code).
  so, a C++ compiler may generate four additional program sections:

  .init   - followed by pointers to library initializers
  .ctor   - followed by pointers to application constructors
  .dtor   - followed by pointers to application destructors
  .fini   - followed by pointers to library finalizers

C++ allows overloaded function names, so the compiler and/or linker need to
  use mangled names, e.g.,
	for fn(int x), the function name becomes fn__i
	for fn(float x), the function name becomes fn__f

additionally, templates in C++ can cause problems with missing routines or
  superfluous routines.  some C++ compilers require a trial linking step to
  cause the linker to generate error messages indicating the missing routines,
  and then those versions of the template are generated.