Simple ARM code generation

Richard Earnshaw Richard.Earnshaw@buzzard.freeserve.co.uk
Tue Aug 15 18:40:00 GMT 2006


On Mon, 14 Aug 2006 15:15:46 PDT, Steve Freeland wrote:
> Hello,
> 
> I'm attempting to use gcc (the WinARM build, see -v output below) to compile 
> the following stub program:
> 
> int AEEMod_Load(IShell *pIShell, void *ph, IModule **ppMod)
> {
>     return ENOMEMORY; /* defined to "2" */
> }
> 
> The output disassembles to the following:
> 
> Disassembly of section .text:
> 
> 00000000 <AEEMod_Load>:
>    0:   e1a0c00d        mov     ip, sp
>    4:   e92dd800        stmdb   sp!, {fp, ip, lr, pc}
>    8:   e24cb004        sub     fp, ip, #4      ; 0x4
>    c:   e24dd00c        sub     sp, sp, #12     ; 0xc
>   10:   e50b0010        str     r0, [fp, #-16]
>   14:   e50b1014        str     r1, [fp, #-20]
>   18:   e50b2018        str     r2, [fp, #-24]
>   1c:   e3a03002        mov     r3, #2  ; 0x2
>   20:   e1a00003        mov     r0, r3
>   24:   e24bd00c        sub     sp, fp, #12     ; 0xc
>   28:   e89da800        ldmia   sp, {fp, sp, pc}
> 
> This code crashes the device I'm working with.
> 
> There seems to be a problem with the use of stmdb and ldmia to save and resto
> re the register context to the stack.  The stmdb instruction saves 4 register
> s, and the ldmia only restores 3 of them, one of which (sp) isn't in the orig
> inal 4.  This trick seems to be common, but I don't understand how it works. 
>  What order are the registers saved and loaded in?  As far as I can tell, at 
> the end the pc register ends up with either the original fp or sp.
> 
> What needs to happen is for the original sp to be restored, and the original 
> lr to be loaded into pc (the "return").
> 
> If I change the two last lines to the following:
> 
>   24:   e24bd004        sub     sp, fp, #4      ; 0x4
>   28:   e12fff1e        bx      lr
> 
> The code works correctly.  Can anyone explain this to me?

Hmm, the code looks correct to me (note that although IP is saved, this is just a copy of SP).

Let me take a guess.  You are using something like an ARM920 (or an ARM7TDMI) device, and you are calling this function from Thumb code.  If so, then you need to compile your function with -mthumb-interwork, then it will generate a return sequence that switches correctly back to Thumb.

R.




More information about the Gcc-help mailing list