Why does stmfd/ldmfd jump back to sub?
Solution 1
There are a couple of issues with your code.
- The main code never returns anywhere, which means after your code returns from the sub it will start again at "sub:" because thats your return point. As lr did not change, it will be stuck in a loop between stmfd/ldmfd. You need to call the exit-function of your system.
- There is no reason to save r1, r2, lr. You're not changing them in your code, also r0-r3 and r12 are caller saved registers anyway.
Solution 2
Note that you have placed your subroutine directly following the instruction that calls it:
bl sub
sub: stmfd sp!,{r1-r2,lr}
ldr r0,[r1,r2,LSL #2]
ldmfd sp!,{r1-r2,pc}
So what happens when you return from the first call to sub
? It will return to the instruction following the bl
, i.e. the stmfd sp!,{r1-r2,lr}
. So the subroutine effectively returns to the beginning of itself. And it will keep doing so because there are no additional implicit or explicit writes to lr
.
Admin
Updated on July 14, 2022Comments
-
Admin almost 2 years
I am doing a project for UNI and have a problem.
We are learning how to push/pop registers onto stack when calling a subroutine.
I need to write a subroutine to convert a decimal number 0-15 into a corresponding hex ASCII code, and keep the value of all registers except
r0
, where the result should be stored. I have a table of ASCII codes, and basically just add thenumber*4
to the starting address of the ASCII table, and store the value back intor0
.I get the right result, but the subroutine loops. It keeps jumping from
ldmfd
tosub
endlessly. Any idea why?main: adr r0,num adr r1,ascii ldr r2,[r0] bl sub sub: stmfd sp!,{r1-r2,lr} ldr r0,[r1,r2,LSL #2] ldmfd sp!,{r1-r2,pc} /* variables here */ num: .word 15 ascii: .word 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x41,0x42,0x43,0x44,0x45,0x46 /* end variables */