Continue on how CPU works. As we already know that CPU only knows numbers and calculate number. And So a natural question is "how CPU loops and create condition if the CPU only know how to calculate?".
To put it simply, CPUs have special instructions that allow them to jump between instructions. We can "emulate" loop and condition, for example in my CPU simulation i have this instruction called JZ (jump if zero). As the name suggests, it jumps to another instruction if a certain value is zero.
example:
LOAD A, 1
LOAD B, 1
CMP A, B
JZ exit
STOREM A, 0 ; store value register A to memory
exit:
HALT
At this point, a question appears: "what value does JZ actually check?" we know that exit is just a label on which line it's referring to, not a value. So how does JZ know when to jump, and This is where branching flags come in.
Before JZ instruction, there's called CMP instruction As the name implies is a compare instruction, like example above it compare register A value and register B value.
During this comparison, the CPU updates special internal flags. The most important ones are:
- Z (Zero flag): true if the result is zero
- N (Negative flag): true if the result is negative
In my simulation, I explicitly store these flags. In real CPUs, these flags are stored in a special register (often called a status register or flags register).
After the calculation for CMP complete the CPU updates the Z and N flags. And when JZ instruction start they will look at Z flag. And if the the Z flag is true (or 1), execute the jump to chosen location.
Same as Loop, like example below
LOAD A, 4
LOAD B, 1
LOAD C, 1
loop:
SUB A, B ; substract A with B
CMP A, C
JZ exit ; if A == C
JMP loop ; not equal than repeat
exit:
HALT
As you see can see above this instruction is the simplest loop where if A is equal to B exit loop.
To create the loop, we need two jump instructions:
-
JZfor the conditional jump. -
JMPfor the unconditional jump back to the loop.
If the JZ condition is not satisfied, the CPU moves to the next instruction, which is JMP. Since JMP has no condition, the CPU will always follow it.
In my simulation, the code for CMP looks like this:
// get value from register and substract
int temp = reg.r[inst.operandA] - reg.r[inst.operandB];
// check if zero or negative
flag.zero = (temp == 0);
flag.negative = (temp < 0);
programCounter++;
The important rule is that the
CMPinstruction should not store any new value in registers or memory. It only updates the flags.
Of course there is other instruction other than JZ such as:
-
JG(jump if greater), -
JL(jump if less), -
JNZ(jump if not zero),
and many others, depending on the CPU design.
So when you see a code like:
int valueA = 2
int valueB = 3
if (valueA == valueB) {
// do stuff
}
in CPU it basically try to subtract valueA and valueB and if zero condition fulfill (ignoring compiler optimizations).
And from this branching flags alone, there are many possibility you can create in here because from my experience no matter the fancy code is inside are just bunch of condition and loop.
Top comments (0)