The !
denotes writeback of the base register. Base register is the register used to address the memory to be read or written - in your case it's R4
. Writeback means that the base register will be updated with the delta equal to the size of transferred data.
So, the instruction
ldm r4!, {r0, r1, r2, r3}
can be represented by the following pseudocode:
r0 = *(int)(r4)
r1 = *(int)(r4+4)
r2 = *(int)(r4+8)
r3 = *(int)(r4+12)
r4 = r4 + 16 // writeback (16 bytes transferred)
In the variant without !
the writeback doesn't happen so R4
retains the original value.
In the LDR
and STR
instructions you may also encounter pre-indexed and post-indexed notation:
LDR R0, [R4, #4] ; simple offset: R0 = *(int*)(R4+4); R4 unchanged
LDR R0, [R4, #4]! ; pre-indexed: R0 = *(int*)(R4+4); R4 = R4+4
LDR R0, [R4], #4 ; post-indexed: R0 = *(int*)(R4+0); R4 = R4+4
For more information see the ARM Assembler Guide.
objdump -M intel