Jump instructions - CodeAbbey/intel4004-emu GitHub Wiki
All instructions we have learned previously are intended for "sequential" execution - i.e. in the same order they are written in your source.
However they could not be very useful if CPU have no ability to test some conditions and perform some choices depending on them.
###Unconditional jumps
Let us at first discuss simple jumps. They test no conditions and work as goto
operators:
JUN
- jumps unconditionally to specified code address
Since it is inconvenient to calculate code addresses manually, we will use labels to mark certain places in our sources and specify them instead of addresses. Note that labels themselves are not instructions (CPU knows nothing about your source). For example:
ldm 5
xch r0
jun skip_few
ldm 6
xch r1
skip_few:
ldm 7
xch r2
Run this to see that values 5
and 7
were stored to r0
and r2
but the middle fragment was skipped because of JUN
instruction. Note that label is just an arbitrary identifier ending with colon.
In this example we can calculate that label skip_few
equals to address $6
so we can write jun 6
instead.
###Conditional Jumps
CPU can test few conditions to decide whether to jump or not. Most useful of them for us are those on the state of Carry flag (set or clear) and of Accumulator (zero or not). All these are performed by JCN
instruction which uses modifier of special kind before label:
JCN C0
- jump if Carry is not set (cy = 0)JCN C1
- jump if Carry is set (cy = 1)JCN AZ
- jump if Accumulator equals to zeroJCN AN
- jump if Accumulator is not zero
If the condition holds, this instruction jumps to supplied address. Otherwise it simply skips to next instruction without doing anything.
Consider an example of summation 4+3+2+1
in a loop:
ldm 4 ; load 4 to r0 - it will be counter
xch r0
one_more:
clc ; add r0 to r1 which will hold the total
ld r1
add r0
xch r1
ld r0 ; decrement r0 via acc
dac
xch r0
jcn c1 one_more ; and jump if there was no borrow
Special form of Conditional Jump is represented by ISZ
(increment and skip if zero) instruction which is also a special form of increment on register:
ISZ
increment register and jump to target address if register does not become zero
This instruction may be helpful in creating loops running for given amount of iterations (like for-loop
).
###Subroutine jumps
There are two instructions providing functionality of subroutines - i.e. pieces of code where you can jump and after doing something return back to instruction following the initial jump:
JMS
- jump to subroutine - works asJUN
but return address (i.e. of the next instruction) is pushed into stack of processorBBL
- "branch back and load" - pops the address from stack and jumps to it - so it is a return from subroutine; it additionally loads supplied value to accumulator (e.g.bbl 7
) which may serve as an error code etc
Here is a simple example:
ldm 0
xch r0
jms add_three
jms add_three
jms add_three
jun finish
add_three:
ld r0
iac
iac
iac
xch r0
bbl 0
finish:
nop
Running this example you will see that r0
is changed to 9
because add_three
subroutine is called thrice.