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.