Where a game's randomness comes from
Almost every cartridge carries a linear congruential generator: one 32-bit seed in RAM, multiplied by a big odd constant and offset by another, with the new value written straight back over the old one. It is four lines of C and it is instantly recognisable in a listing, because the two constants are far too wide for a mov and land in the literal pool next to the seed's own address.
The low bits of an LCG are close to worthless - bit 0 alternates every call, bit 1 has a period of four - so the usable randomness is at the top. That is why these routines almost always end by shifting the seed down rather than returning it whole.
Here is one of those generators, rolling a damage value:
0 push {lr}
2 ldr r2, [pc, #24] (->28)
4 ldr r1, [r2, #0]
6 ldr r0, [pc, #24] (->32)
8 mul r0, r1
10 add r0, #1
12 str r0, [r2, #0]
14 lsr r0, #24
16 mov r1, #6
18 bl __umodsi3-4
22 pop {r1}
24 bx r1
26 .hword 0
28 .word gDamageSeed
32 .word 69069
Read the pool first. .word gDamageSeed is the global's address, printed by name because it is a relocation; .word 69069 is the multiplier. The addend is 1, which fits in an 8-bit immediate, so it never reaches the pool at all - it is the add r0, #1. Then str r0, [r2, #0] puts the new seed back and lsr r0, #24 keeps the top byte.
The bl is the problem. % 6 has no instruction on this machine, so it becomes a call to __umodsi3, and the call drags in push {lr}, pop {r1} and bx r1 - a leaf function turned into a caller for the sake of one modulo. On a 16.78 MHz ARM7 running from cartridge ROM that is dozens of wasted cycles, every time anything in the game needs a number.
So shipped code does not divide. It scales instead: take a value that is already uniform across some width, multiply it by the size of the range you want, and shift the product back down by that same width. The result lands inside the range with no division anywhere, which is why your target contains no bl at all.
Your task
Write func_08410b40 to reproduce the target assembly.