When both answers arrived in registers
The previous lesson seeded a constant into a register before the compare and conditionally overwrote it. The same skeleton handles a choice between two values that both arrived in registers, and the interesting part is where the result gets accumulated.
0 cmp r0, r1
2 ble 6 ~>
4 mov r1, r2
6 ~>mov r0, r1
8 bx lr
The result is built in r1, which already held one of the two candidates — so that candidate needs no seed at all, because it is where it has to be already. mov r1, r2 is the overwrite, ble skips it when the relation the source wrote is false, and mov r0, r1 delivers whatever survived. Five instructions and no join branch.
Write the same decision as an if with a return in each arm and it comes out longer:
0 cmp r0, r1
2 bgt 8 ~>
4 mov r0, r1
6 b 10 ~>
8 ~>mov r0, r2
10 ~>bx lr
There is no accumulator here. Each arm moves its own answer straight into r0, and the arm laid down first has to jump over the second, so both candidates cost an instruction and the join costs a third. Same decision, same two values, six instructions instead of five.
The shape to watch for is what happens when the accumulator has to be r0 itself. r0 arrives holding the first argument, so anything else being accumulated there means evicting that argument first, and the function opens with a pair of movs: one argument copied out to a scratch register, the other installed in r0. After that pair, the value in r0 is the one the function returns when the branch is taken and nothing else runs, and the scratch register holds the answer that costs a mov.
Read that pair before you read the compare. It tells you which of the two values gets the free path, and it fixes what the compare's operands mean — the same two register numbers say opposite things depending on which way the moves went.
Your target opens with that pair. Work out which value ends up in r0, then read the compare and its branch together for the condition that leaves it there.
Your task
Write func_0814294c to reproduce the target assembly.