One instruction that loads and advances
Thumb has no post-increment load. There is no ldr r0, [r3], #4 — the encoding does not exist. What Thumb does have is load-multiple with writeback, ldmia rN!, {list}, which loads a list of registers from consecutive addresses and leaves the base pointing past the last one. Put exactly one register in the list and you have a post-increment load built out of the only instruction that offers writeback.
That is why almost every word-sized array walk in an agbcc build looks like this. Here is a loop that fills an array with -1:
0 cmp r1, #0
2 ble 16 ~>
4 mov r2, #1
6 neg r2, r2
8 ~>stmia r0!, {r2}
10 sub r1, #1
12 cmp r1, #0
14 bne 8 ~>
16 ~>bx lr
stmia r0!, {r2} is the store mirror: write r2 to [r0], then advance r0 by 4. Compare it with the halfword fill from the last lesson, which needed strh followed by add r0, #2. There is no halfword load-multiple, so halfwords and bytes pay for their advance separately and words do not.
The -1 in the preheader is the constant-building rule you already know. Thumb mov takes an unsigned 8-bit immediate, so a negative constant is built as the positive one and negated: mov r2, #1 / neg r2, r2.
Three things have to be true before gcc reaches for the load-multiple form: the element is exactly four bytes, the pointer is read once per trip, and the advance sits in the same straight run of instructions as the load. Break any of them and the loop falls back to a plain ldr and a separate add. Later lessons in this chapter break each of them in turn, and now you know what the undamaged version looks like.
Your target's loop is built on this instruction. The part to read closely is what sits between the load and the countdown.
Your task
Write func_08185918 to reproduce the target assembly.