Search code examples
assemblyarm

After STM instruction, why does R6 register hold memory location of 10, 11, 12?


In Wiley's Practical Reverse Engineering book, page 59, the following example is used to explain the LDM/STM instructions.

Shouldn't line 30 show R6 with the values of r3, r4, r5? Doesn't line 10 store the values in R6 at the memory locations of the destination?

02: Breakpoint 1 at 0x8344
03: (gdb) disas main
04: Dump of assembler code for function main:
05:    0x00008344 <+0>:     ldr     r6, =mem  ; edited a bit
06:    0x00008348 <+4>:     mov     r0, #10
07:    0x0000834c <+8>:     mov     r1, #11
08:    0x00008350 <+12>:    mov     r2, #12
09:    0x00008354 <+16>:    ldm     r6, {r3, r4, r5}  ; IA mode
10:    0x00008358 <+20>:    stm     r6, {r0, r1, r2}  ; IA mode
11: …
12: (gdb) r
13: Breakpoint 1, 0x00008344 in main ()
14: (gdb) si
15: 0x00008348 in main ()
16: (gdb) x/3x $r6
17: 0x1050c <mem>:  0x00000001      0x00000002      0x00000003
18: (gdb) si
19: 0x0000834c in main ()
20: …
21: (gdb)
22: 0x00008358 in main ()
23: (gdb) info reg r3 r4 r5
24: r3             0x1      1
25: r4             0x2      2
26: r5             0x3      3
27: (gdb) si
28: 0x0000835c in main ()
29: (gdb) x/3x $r6
30: 0x1050c <mem>:  0x0000000a      0x0000000b      0x0000000c

Solution

  • The fact that your ldm instruction took what was at the memory location pointed to by r6 and loaded that into r3/4/5 (a memory to register operation), should be a dead giveaway that stm will do the opposite (a register to memory operation).

    In other words, it will store r0/1/2 (which you'e set to 10/11/12 decimal or a/b/c hexadecimal) into the memory pointed to by r6, exactly what you're seeing:

    30: 0x1050c <mem>:  0x0000000a      0x0000000b      0x0000000c
    

    This matches the other load/store instructions on ARM and, indeed, quite a lot of other CPUs, you:

    • load from memory; and
    • store to memory.