WARNING: Answer for newbies. May bore experienced users to death.
I'm not sure if you misused the terminology or if you really want to use predicated instructions1.
In the latter case, using ARM v6 predication as a study case (and inheriting your premises about register usage), the assembly is simply
;r1 = A r2 = B r3 = C r4 = D r5 = E
;
;A, B unsigned | ;A, B signed
|
cmp r1, r2 | cmp r1, r2
|
movhi r3, r1 | movgt r3, r1
movhi r4, r2 | movgt r4, r2
movhi r5, #0 | movgt r5, #0
|
movls r3, r2 | movle r3, r2
Here I gave two versions based on the sign of the involved variables.
movhi
means move if higher. movls
means move if lower or same.
movgt
means move if greater. movle
means move if less or equal.
They mean the same arithmetic comparison, it is just that the latter uses the proper flags for signed numbers.
I grouped the instructions, so it is easy to identify the if-then and the else blocks.
Note how instructions in the same block have the same suffix (e.g. hi
and ls
).
What really makes this code a if-then-else construct rather than something else is the fact that the conditions hi
-ls
and gt
-le
are mutually exclusive (only one of the twos can be true).
So only one block of instructions can be executed.
Using non mutually exclusive conditions give rise to multiple if-then-else statements.
If you misused the terminology and you actually wanted just to implement a conditional statement (or selection), i.e. an if-then-else, then the usual approach is a conditional branch2 as Nutan already shown.
Here a slightly more readable version:
cmp r1, r2
bls _A_less_same_B
mov r3, r1
mov r4, r2
eor r5, r5, r5
b _end_if
_A_less_same_B:
mov r3, r2
_end_if:
Up to you the burden to convert this code to work with signed integers.
The fancy words ending with a colon (:
) are called labels, they are an useful way to name points in code (and data)3.
Think about that as flexible line numbers.
b
means branch, once it is executed the next instruction is fetched from the label (address) specified as operand (for example from _end_if
).
bls
is just a predicated b
(bls
means branch if less or same), commonly known as conditional branch.
Conditional branches are just like normal branches but they can be "ignored" if the conditions specified fails to meet.
A conditional jump is said to be taken if the conditions are met and the CPU execute the jump, thereby fetching the next instructions from the label specified as operand.
It is said to be not taken if the conditions are not met and the CPU continue the execution from the instruction after the branch (the program flow fall through).
The "conditions" usually means flags set and cleared.
Some instruction, like cmp
, set and clear these flags.
Other instructions, like bls
use these flags.
The flags are hold in a dedicated registers (ps
in ARM) but there are architectures, most notably MIPS, which don't have a flags register.
You can use your finger to simulate the program flow. For example if A > B
the flow is as follow:
[Start Here]
¯¯¯¯+¯¯¯¯¯
cmp r1, r2 |
bls _A_less_same_B + [Branch not taken, fall through]
|
mov r3, r1 |
mov r4, r2 |
eor r5, r5, r5 |
|
b _end_if +--[Branch always taken]----+
|
_A_less_same_B: |
mov r3, r2 |
|
_end_if: +--[Land here]--------------+
|
V
The bend is mean to picture a "jump over" the code that we want to skip (the else in this case).
I don't recognize the assembly flavor of your question, so I cannot help with writing concrete examples.
I wouldn't do it anyway as I feel that this general explanation is enough and in the hope that such lack of effort on my side will spur you into attempting solving the exercise by yourself.
Which is a mandatory step on the route of learning.
1 Instruction that are fetched, decoded, (probably issued too) but only executed if particular flags are set or cleared.
2 Note that conditional branches are best avoided if possible. Depending on the targeting micro-architecture there can be a more optimal way to achieve the same result. This was just worth noting, don't bother with it right now.
3 Actually offsets that will become addresses.