I have many thumb and cortex-m based examples http://github.com/dwelch67 
As Joachim pointed out you are missing the first entry in the vector table, the stack pointer.  the cortex-m does not have the same vector table as an arm, meaning one that boots up in arm mode with arm instructions.
To complete the answer though, for the cortex-m you can setup the stack by putting the starting value for the stack pointer in that first word location 
.cpu cortex-m3
.thumb
.word   0x10008000  /* stack top address */
.word   _start      /* 1 Reset */
.word   hang        /* 2 NMI */
.word   hang        /* 3 HardFault */
.word   hang        /* 4 MemManage */
you can certainly once running set the stack pointer manually as you would with an arm in arm mode or most other processors.  
I would have your code fall into an infinite loop so that, as written, you dont fall into undefined instructions, etc. (should be 0xFFs, which on the cortex-m0 I think is an undefined, on a -m3 or -m4 with armv7 thumb2 support it might be a real instruction).
Notice that I didnt use the +1 on my vectors.  You need to know your tools.  You need that lsbit set to indicate a thumb address/thumb mode on the branch.  Although I learned a lesson on that (will have to find the so question) 
Arm/Thumb: using BX in Thumb code, to call a Thumb function, or to jump to a Thumb instruction in another function
With the gnu assembler if you put a directive .thumb_func before a label, that label is marked to be a thumb label and the gnu tools will then use the address|1.
.thumb_func
.globl _start
_start:
You need to build and disassemble every now and again to make sure your table is being built correctly and branches and such are using the proper address.
   0:   10008000    andne   r8, r0, r0
   4:   0000005b    andeq   r0, r0, fp, asr r0
   8:   00000050    andeq   r0, r0, r0, asr r0
   c:   00000050    andeq   r0, r0, r0, asr r0
  10:   00000050    andeq   r0, r0, r0, asr r0
see, apparently I have a bug in one of my examples...it never does anything but reset (no interrupts used in the example, so that is how I got away with not knowing). forgot the .thumb_func
hang:   b .
produced
00000050 <hang>:
  50:   e7fe        b.n 50 <hang>
change to 
.thumb_func
hang:   b .
and the vector table goes to 
00000000 <hang-0x50>:
   0:   10008000    andne   r8, r0, r0
   4:   0000005b    andeq   r0, r0, fp, asr r0
   8:   00000051    andeq   r0, r0, r1, asr r0
   c:   00000051    andeq   r0, r0, r1, asr r0
  10:   00000051    andeq   r0, r0, r1, asr r0
  14:   00000051    andeq   r0, r0, r1, asr r0
this is interesting, change the code to 
.cpu cortex-m3
.thumb
.word   0x10008000  /* stack top address */
.word   _start+1      /* 1 Reset */
.word   hang+1        /* 2 NMI */
.word   hang+1        /* 3 HardFault */
.word   hang        /* 4 MemManage */
.word   hang        /* 5 BusFault */
and it doesnt really do a plus one but instead an or one.
00000000 <hang-0x50>:
   0:   10008000    andne   r8, r0, r0
   4:   0000005b    andeq   r0, r0, fp, asr r0
   8:   00000051    andeq   r0, r0, r1, asr r0
   c:   00000051    andeq   r0, r0, r1, asr r0
  10:   00000051    andeq   r0, r0, r1, asr r0
That is a bit disturbing.  The bottom line though, two things, with a cortex-m you can setup the stack pointer in the vector table, second, when starting a new project disassemble and examine the vector table to make sure it is what you are expecting.  Esp if it isnt doing what you think it should.