Control
Control of the code execution flow
Machine code provides two basic low-level mechanisms for implementing conditional behavior: (Machine code provides two basic low-level mechanisms for implementing conditional behavior)
- It tests data values and changes the control flow or data flow based on the results of these tests
6.1 Condition Codes
The CPU maintains a series of single-bit condiiton code registers describing attributes of the most recent arithmetic or logical operations
(unit condition code registers describing the attributes of the most recent arithmetic or logical operations)
- CF: Carry Flag (carry flag) The most recent operation generated a carry out of the most significant bit (the most recent operation generated the execution of the most significant bit) ------> Mainly used to detect overflow of unsigned operations
- ZF: Zero Flag. (Zero flag) The result of the latest operation is zero
- SF: Sign Flag. (Sign Flag) The most recent operation produced a negative value
- OF: Overflow Flag (overflow flag) The most recent operation caused 2's complement overflow
For example, if we have this calculation t = a + b
then these registers will be calculated like this
CF (unsigned) t < (unsigned) a Unsigned Overflow
ZF (t == 0) Zero
SF (t < 0) Negative
OF (a < 0 == b < 0) && (t < 0 != a < 0) Sign Overflow
6.2 Jump Instructions
- Jump instructions are usually translated as a label, jump to this label here
if-else statement in C language
if(test-expr)
then-statement
else
else-statement
Assembly will convert it into the following form
t = text-expr
if(!t)
goto false;
then-statement
goto done;
false:
else-statement
done:
6.3 Use conditional transfer to implement conditional branching
The operation to achieve conditions is traditionally done through control:
- If correct, take one path
- On the contrary, there is another way
An alternative strategy is to use conditional transfer of data
- In fact, I calculated both, and took whichever one was the result.
long absdiff(long x, long y){
long result;
if(x < y)
result = y - x;
else
result = x - y;
return result
}
会被翻译为
long cmovdiff(long x, long y){
long rval = y - x;
long eval = x - y;
long ntest = x >= y;
if(ntest) rval = eval;
return rval;
}
The reason why conditional transfer of data has better performance is mainly because it can avoid penalties for processor errors.
- Today's processors use very sophisticated branch prediction logic to guess whether each instruction will be executed.
- If the prediction fails, the processor is required to discard the work it has done for all instructions after the jump instruction, and then start from the correct position to fill the pipeline
6.4 Switch statement
Multiple branch predictions can be made based on an integer index value
- Using jump table makes the implementation more efficient