Simple ARM code generation

Steve Freeland
Mon Aug 14 22:18:00 GMT 2006


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 restore the register context to the stack.  The stmdb instruction saves 4 registers, and the ldmia only restores 3 of them, one of which (sp) isn't in the original 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?

Thanks in advance,
- Steve

gcc -v output:
$ c:/Progra~1/winarm/bin/arm-elf-gcc -v
Using built-in specs.
Target: arm-elf
Configured with: ../../gcc-4.1.1/configure --enable-languages=c,c++ --enable-interwork --enable-multilib --with-gcc --with-gnu-ld --with-gnu-as --with-stabs --disable-shared --disable-threads --disable-libssp --disable-libstdcxx-pch --disable-libmudflap --disable-win32-registry --disable-nls --disable-debug --without-headers --with-newlib --target=arm-elf --prefix=c:/WinARM -v
Thread model: single
gcc version 4.1.1 (WinARM)

More information about the Gcc-help mailing list