You could simplify this to: LDR pc, main_address How are you checking the pc value? When running code the PC points at the instruction being fetched - not the one being executed.
LDR pc, main_address
reset_handler: # copy from flash(0x00000000) to ram eor r0, r0 ldr r1, ram_start ldr r2, ram_end sub r2, r2, r1 1: ldr r3, [r0], #4 str r3, [r1], #4 subs r2, #4 bne 1b # install a stack ldr sp, stack_top mov fp, sp # branch to main ldr pc, main_address b reset_handler ram_start: .extern __ram_start .word __ram_start // == 0x40000100ram_end: .extern __ram_end .word __ram_end // == 0x40000200stack_top: .word __ram_end + 0x1000 main_address: .extern main .word main
I am not familiar with the GNU assembler syntax as I use the ARM tools. However, based on the ARM syntax it looks what you are doing is getting the address of the label. Have you tried:.extern mainldr pc, =main
.extern mainldr pc, =main
Hmm... Since you mention a hardcoded value works, and decrement by 4, I wonder if the size is actually not a multiple of 4 when working it out? It looks like the code might loop if it wasn't.
Actually, pc is correctly loaded, and I guess there isa problem with my copy, but I dont see which one.main is a naked function and has no local variable,so it doesnot use the stack at all...When I replace the first sub to compute the size witha harcoded one (ie. mov r2, #0x1000), it works...