implementation of c=a*b using ONLY inc dec and jnz commands
I'm not going to give the full answer, but the key here is that you have to define a mov
routine yourself. Assuming dec X
where X
holds 0 produces a negative (or very large) number, that can be done as:
MOV_AD: ; copy value in A to D, using E as scratch space
inc A ; must be non-zero for jnz to work below
COPYLOOP:
inc D
inc E
dec A
jnz COPYLOOP
dec D ; undo the first inc A in D
; E now contains the initial value of A + 1
MOVBACK: ; move value in E back to A
inc A
dec E
jnz MOVBACK
dec A ; undo the first inc A
WIPE_E: ; wipe the scratch space
dec E
jnz WIPE_E
Once you have the appropriate mov
routines, you can implement addition as repeated increment and multiplication as repeated addition. In both, you'll need the inc
trick to get jnz
to work, and in the multiplication routine, you'll need to end with a subtraction.
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
The JNZ instruction can be seen as do .. while structure, an example with @user9876 code :
@_loop1: ; do {
; do {
INC Z ; z++;
INC C ; c++;
DEC B ; b--;
JNZ _loop1 ; } while (b != 0);
;
@_loop2: ; do {
INC B ; b++;
DEC Z ; z--;
JNZ _loop2 ; while (z != 0);
;
DEC A ; a--;
JNZ _loop1 ; } while (a != 0);