Breaking this down step by step:
Original:
C = A * B
Is equivalent to:
C = 0
while A != 0:
dec A
C += B
Is equivalent to:
C = 0
while A != 0:
dec A
# Note: Following block of code changes B but sets it back to
# original value when done
Z = 0
while B != 0:
dec B
inc Z
inc C
B = Z
Is equivalent to:
C = 0
Z = 0
while A != 0:
dec A
# Note: Following block of code changes B but sets it back to
# original value when done
while B != 0:
dec B
inc Z
inc C
while Z != 0:
dec Z
inc B
Now we just need to figure out how to translate this construct:
while LOOP_VAR != 0:
dec LOOP_VAR
... some code here which does not use LOOP_VAR ...
That can be translated to:
# Next 4 lines do "if LOOP_VAR == 0: goto loop_end"
inc LOOP_VAR
dec LOOP_VAR # To set flags
jnz loop_again
goto loop_end
loop_again:
... some code here which does not use LOOP_VAR ...
dec LOOP_VAR
jnz loop_again
loop_end:
And of course, we need to translate that unconditional goto into a conditional one. Fortunately we have lots of variables that are known to be zero, so we can test if one of them is zero:
# Unconditional jump to "loop_end". Note that Q is always zero.
inc Q
dec Q
jnz loop_end
So, putting that all together:
# Next 3 lines do "if A != 0: goto outer_loop_again"
inc A
dec A # To set flags
jnz outer_loop_again
# Unconditional jump to "outer_loop_end". Note that Q is always zero.
inc Q
dec Q
jnz outer_loop_end
outer_loop_again:
# Next 3 lines do "if B != 0: goto addition_loop_again"
inc B
dec B # To set flags
jnz addition_loop_again
# Unconditional jump to "addition_loop_end". Note that Q is always zero.
inc Q
dec Q
jnz addition_loop_end
addition_loop_again:
inc Z
inc C
dec B
jnz addition_loop_again
addition_loop_end:
# Next 3 lines do "if Z != 0: goto move_loop_again"
inc Z
dec Z # To set flags
jnz move_loop_again
# Unconditional jump to "move_loop_end". Note that Q is always zero.
inc Q
dec Q
jnz move_loop_end
move_loop_again:
inc B
dec Z
jnz move_loop_again
move_loop_end:
dec A
jnz outer_loop_again
outer_loop_end:
# Finished!
helt
Edited to add: Actually, there's a slightly simpler way. We can check if A or B are zero at the start, which simplifies it to:
# Check if A is zero, and halt if so
# (So that multiplying by zero gives zero)
inc A
dec A # To set flags
jnz a_non_zero
helt # Multiplying by zero gives zero
a_non_zero:
# Check if B is zero, and halt if so
# (So that multiplying by zero gives zero)
inc B
dec B # To set flags
jnz b_non_zero
helt # Multiplying by zero gives zero
b_non_zero:
outer_loop_again:
addition_loop_again:
inc Z
inc C
dec B
jnz addition_loop_again
move_loop_again:
inc B
dec Z
jnz move_loop_again
dec A
jnz outer_loop_again
# Finished!
helt