Note that assembly language is defined by the tool not the target. For gnu assembler, to date for thumb, particularly with these cortex-ms where you need/want to get the vector table right you started with this problem:
.thumb
.globl _start
_start:
.word 0x20001000
.word reset
.word loop
.word loop
reset:
b reset
loop:
b loop
assemble/dissassemble and you can see the problem
Disassembly of section .text:
00000000 <_start>:
0: 20001000 andcs r1, r0, r0
4: 00000010 andeq r0, r0, r0, lsl r0
8: 00000014 andeq r0, r0, r4, lsl r0
c: 00000014 andeq r0, r0, r4, lsl r0
00000010 <reset>:
10: eafffffe b 10 <reset>
00000014 <loop>:
14: eafffffe b 14 <loop>
(once you know that the vector addresses need to be the address orred with 1)
.thumb
.globl _start
_start:
.word 0x20001000
.word reset
.word loop
.word loop
.thumb_func
reset:
b reset
loop:
b loop
the minimum but clean solution is to add .thumb_func to indicate that the next label you find is a thumb function not a generic address.
(you have to link not just assemble/disassemble)
Disassembly of section .text:
00000000 <_start>:
0: 20001000 andcs r1, r0, r0
4: 00000011 andeq r0, r0, r1, lsl r0
8: 00000012 andeq r0, r0, r2, lsl r0
c: 00000012 andeq r0, r0, r2, lsl r0
00000010 <reset>:
10: e7fe b.n 10 <reset>
00000012 <loop>:
12: e7fe b.n 12 <loop>
and that fixed one vector.
.thumb
.globl _start
_start:
.word 0x20001000
.word reset
.word loop
.word loop
.thumb_func
reset:
b reset
.thumb_func
loop:
b loop
and that fixed the other.
Disassembly of section .text:
00000000 <_start>:
0: 20001000 andcs r1, r0, r0
4: 00000011 andeq r0, r0, r1, lsl r0
8: 00000013 andeq r0, r0, r3, lsl r0
c: 00000013 andeq r0, r0, r3, lsl r0
00000010 <reset>:
10: e7fe b.n 10 <reset>
00000012 <loop>:
12: e7fe b.n 12 <loop>
add some C
.thumb
.globl _start
_start:
.word 0x20001000
.word reset
.word loop
.word fun
.thumb_func
reset:
b reset
.thumb_func
loop:
b loop
void fun ( void )
{
}
Disassembly of section .text:
00000000 <_start>:
0: 20001000 andcs r1, r0, r0
4: 00000011 andeq r0, r0, r1, lsl r0
8: 00000013 andeq r0, r0, r3, lsl r0
c: 00000015 andeq r0, r0, r5, lsl r0
00000010 <reset>:
10: e7fe b.n 10 <reset>
00000012 <loop>:
12: e7fe b.n 12 <loop>
00000014 <fun>:
14: 4770 bx lr
16: 46c0 nop ; (mov r8, r8)
Then look at the output of the C compiler
.cpu arm7tdmi
.eabi_attribute 20, 1
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 26, 1
.eabi_attribute 30, 2
.eabi_attribute 34, 0
.eabi_attribute 18, 4
.file "fun.c"
.text
.align 1
.p2align 2,,3
.global fun
.arch armv4t
.syntax unified
.code 16
.thumb_func
.fpu softvfp
.type fun, %function
fun:
@ Function supports interworking.
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
@ link register save eliminated.
@ sp needed
bx lr
.size fun, .-fun
.ident "GCC: (GNU) 8.2.0"
(doesnt matter that I defaulted to the arm7, but there is .thumb_func)
some assembly languages will have directives like proc or function or other similar things that you use to declare a label as a function rather than just a generic address to something, so when trying other assemblers for arm you may run into that.
if this uses the gnu assembler then .thumb_func should fix it. I would in your mind think if this as an orring with one not an adding with one in case the address is correct you might end up breaking it with the just add one to everything notion.
Same goes for function pointer stuff in C you have to be careful and can run into this.
void loop ( void );
void hop ( unsigned int );
void fun ( void )
{
unsigned int x;
x = (unsigned int) loop;
hop(x);
}
void more_fun ( void )
{
unsigned int x;
unsigned short z[4];
z[0]=0x46c0;
z[1]=0x4770;
z[2]=0x46c0;
z[3]=0x46c0;
x = (unsigned int) z;
hop(x);
}
00000012 <loop>:
12: e7fe b.n 12 <loop>
00000014 <hop>:
14: 4700 bx r0
00000018 <fun>:
18: b510 push {r4, lr}
1a: 4803 ldr r0, [pc, #12] ; (28 <fun+0x10>)
1c: f7ff fffa bl 14 <hop>
20: bc10 pop {r4}
22: bc01 pop {r0}
24: 4700 bx r0
26: 46c0 nop ; (mov r8, r8)
28: 00000013 andeq r0, r0, r3, lsl r0
0000002c <more_fun>:
2c: b500 push {lr}
2e: 4b05 ldr r3, [pc, #20] ; (44 <more_fun+0x18>)
30: b083 sub sp, #12
32: 9300 str r3, [sp, #0]
34: 4b04 ldr r3, [pc, #16] ; (48 <more_fun+0x1c>)
36: 4668 mov r0, sp
38: 9301 str r3, [sp, #4]
3a: f7ff ffeb bl 14 <hop>
3e: b003 add sp, #12
40: bc01 pop {r0}
42: 4700 bx r0
44: 477046c0
48: 46c046c0
not that you are going to run code like that but you can see the problem.
and a fix
void more_fun ( void )
{
unsigned int x;
unsigned short z[4];
z[0]=0x46c0;
z[1]=0x4770;
z[2]=0x46c0;
z[3]=0x46c0;
x = (unsigned int) z;
hop(x|1);
}
0000002c <more_fun>:
2c: b500 push {lr}
2e: 4b06 ldr r3, [pc, #24] ; (48 <more_fun+0x1c>)
30: b083 sub sp, #12
32: 9300 str r3, [sp, #0]
34: 4b05 ldr r3, [pc, #20] ; (4c <more_fun+0x20>)
36: 4668 mov r0, sp
38: 9301 str r3, [sp, #4]
3a: 2301 movs r3, #1
3c: 4318 orrs r0, r3
3e: f7ff ffe9 bl 14 <hop>
42: b003 add sp, #12
44: bc01 pop {r0}
46: 4700 bx r0
48: 477046c0
4c: 46c046c0
what you may very well do is write a bootloader and to get the hop into the loaded code right you need to solve it there are use a function pointer things you can try and maybe not write some asm, but I recommend the asm and orr with one, more likely to get it to work.