Conditional Jump instructions?
Doing a compiler design course:
What is meant by a conditional jump instruction? I am C/C++ based programmer so if there is any code samples in that paradigm you could share to help me understand this better.
What do they mean by unlimited conditional jump instructions?
An example of a stateme开发者_StackOverflow中文版nt from the book:
Many processors have conditional jump instructions only for conditional jumps with a limited range. For example, the target of the jump may not be further than 128 bytes away from the current program counter. Sometimes, an assembler for such a processor still allows unlimited conditional jumps.
Would I have to know assembler programming to understand this?
I'd love links to reference materials for further reading.
Many processors have conditional jump instructions only for conditional jumps with a limited range. For example, the target of the jump may not be further than 128 bytes away from the current program counter.
Take an x86 conditional jump like JNZ
for example which means "jump if the processor's Zero flag is not set" (the processor flags would be set or cleared by a previous arithmetic operation).
The JNZ
opcode has an operand which says how far to jump. For the JNZ
opcode the operand is encoded using a single byte (i.e. only the first byte after the opcode is interpreted as the operand; the next byte is the begining of the next opcode), so it can specify a jump of no further than plus or minus 128 bytes.
[It uses a short, 1-byte operand because a short jump is the most common case, and this optimization for the most common case helps to make the overall code smaller].
Sometimes, an assembler for such a processor still allows unlimited conditional jumps.
This means when when you write in high-level assembly, you can write ...
jnz distant_label
[other instructions]
distant_label:
... even when the distant label is more than 128 bytes away. How can it do this, when the CPU itself only supports short conditional jumps? Probably because the assembler (which 'assembles' your assembly language, like a compiler) automatically inserts some extra necessary opcodes, so that what actually ends up being emitted is something like ...
jz nearby_label
jmp distant_label
nearby_label:
[other instructions]
distant_label:
... where:
- Instead of
jnz distant_label
there'sjmp distant_label
--JMP
is an unconditional jump, which has a larger operand and can jump an unlimited distance - Instead of
jnz distant_label
there'sjz nearby_label
-- 'JNZ' is replaced by 'JZ' which means instead of "jump to distant label if the flag is not zero" it does "jump to nearby label, so don't do the far jump, if the flag is zero" (which ends up meaning the same thing as what you wrote, because "jump if not zero" means the same thing as "don't jump if zero").
I think this addresses your question: in the Microchip PIC18F series, for example, you have a bra
(branch) command and a goto
command. They are effectively the same, but the difference is that the bra
command can only jump to a location -1024 to +1023 words from its location, and it uses only one word of program memory. A goto
command can jump anywhere in program memory, but it requires an two words of program memory to allow jumping anywhere.
If you incorrectly try branching to a label too far away, the compiler will give you an error.
Those extra words can make a difference when you only have, say, 2K words of program memory, of course.
bra
and goto
by themselves are unconditional jumps; however, there are several conditional branch commands, such as bc
(branch if carry), bz
(branch if zero), bnz
(branch if not zero), etc, which all check the status registers from the last (arithmetic) operation, and only perform the branch if the specified condition was true.
If you need a conditional goto
, then you would have something like
DELAY
nop
nop
decfsnz DelayCount
goto DONE_WITH_DELAY
bra DELAY
Where we perform two no-ops to "sleep" for a moment; decrement a "variable" named DelayCount
, and if DelayCount
is zero, then we unconditionally jump to the code labeled DONE_WITH_DELAY
; if it is not zero, we jump back up to the DELAY
label and do it again. (decfsnz
means "Decrement f
, skip if not zero)
Regarding the conditional branch, you can start at this definition:
Branch (computer science):
There are two usual forms of branch instruction: a conditional branch that can be either taken or not taken, depending on a condition such as a CPU flag, and an unconditional branch which is always taken.
The if, for, while
C statements are compiled to conditional jump assembly operators. While the goto
statement is compiled to an unconditional jump operator.
Regarding the limited/unlimited range of the jump: The range is the "distance" in the memory between the address of the jump instruction and the address to which jumping. The Program counter article in the wikipedia can give you more information on this matter.
You don't have to know assembler programming in order to understand these subjects, but I'd recommend to learn the basics of the CPU architecture.
A conditional jump would logically turn this if statement:
if(a == b)
{
// do something
}
// do something else
into this:
if(!(a==b)) goto somethingElse;
// do something
somethingElse:
// do something else
The if(!(a==b))
line would then turn into the assembly command:
CMP A, B
JNE somethingElse
Now, as for "unlimited conditional jump", I assume they mean far jumps?
A conditional jump is like
if (condition) goto
in C. An unconditional jump is like
goto
in C.
I don't know what "unlimited" means though. It could be specific to the particular processor under discussion.
In short terms:
Conditional means something like
if(condition)
{
//condition met
}
else
{
//condition no met
}
That means program flow is changed depending ot the conditional expression.
Unconditional jumps are typical compiler implementations of goto statements or function calls.
精彩评论