Let’s say there was no command block, so it would look something like this (no optimization):
var x = 8;
if (x < 4) goto TRUE;
print("x é maior do que 4!");
goto FIM;
:TRUE
print("x é menor do que 4!");
:FIM
imagining that you understand the concept of goto
and label that I used in TRUE
, if you don’t know, it’s a specific question.
But it still doesn’t explain how if
is executed.
Well, the processor knows how to make a decision, there is ready a code that knows whether to do something or not to do something, that’s all, it does not analyze the condition. This is usually called branch, i.e., it picks up a branch or other branch. On Intel is the instruction jz
( or je
, jne
, or others see a list).
Internally it has a lot of logical ports that will run an algorithm to make this decision, but basically what it does is deviate the execution (changes the register PC
which is the registrar that stores the address of the next instruction to be executed) if there is a value in a flag of the recorder (see their list).
That one flag register will have a value according to the last execution of a previous possibly comparative instruction (not necessarily) that has changed one of the flags which will be checked. Then the condition is made separately from the if
. I always said that deep down what happens is this (many people do not understand and think that the condition is part of the if
:
var x = 8;
var cond = x < 4;
if (cond) goto TRUE;
print("x é maior do que 4!");
goto FIM;
:TRUE
print("x é menor do que 4!");
:FIM
Note that the if
and the goto
are still one thing, only one instruction causes deviation conditionally (other than instruction JMP
which causes the deviation unconditionally and is the goto
simple).
Of course, in some languages this works a little differently because they run on virtual machines, but in essence it’s the same thing. Same goes for different processors.
In fact in C I would compile more or less for this:
.LC0:
.string "x \303\251 menor do que 4!"
.LC1:
.string "x \303\251 maior do que 4!"
teste:
push rbp
mov rbp, rsp
sub rsp, 16
mov DWORD PTR [rbp-4], 8
cmp DWORD PTR [rbp-4], 3
jg .L2
mov edi, OFFSET FLAT:.LC0
mov eax, 0
call printf
jmp .L3
.L2:
mov edi, OFFSET FLAT:.LC1
mov eax, 0
call printf
.L3:
nop
leave
ret
See on Compiler Explorer.
In case the jg
is the instruction that makes the decision (it is jump if flag value is Greater). The instruction CMP
is that it makes the comparison and generates a value in the flag ZF
.
In C# would be this:
.class private auto ansi '<Module>'
{
} // end of class <Module>
.class public auto ansi beforefieldinit C
extends [System.Private.CoreLib]System.Object
{
// Methods
.method public hidebysig
instance void M () cil managed
{
// Method begins at RVA 0x2050
// Code size 26 (0x1a)
.maxstack 8
IL_0000: ldc.i4.8
IL_0001: ldc.i4.4
IL_0002: bge.s IL_000f
IL_0004: ldstr "x é menor do que 4!"
IL_0009: call void [System.Console]System.Console::WriteLine(string)
IL_000e: ret
IL_000f: ldstr "x é maior do que 4!"
IL_0014: call void [System.Console]System.Console::WriteLine(string)
IL_0019: ret
} // end of method C::M
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x206b
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [System.Private.CoreLib]System.Object::.ctor()
IL_0006: ret
} // end of method C::.ctor
} // end of class C
See on Sharplab.
And in Assembly:
; Core CLR v4.700.19.46205 (coreclr.dll) on x86.
C..ctor()
L0000: ret
C.M()
L0000: mov ecx, [0x10998940]
L0006: call System.Console.WriteLine(System.String)
L000b: ret
Check in the Sharplab. Then you ask: where is the condition? The compiler realized it could solve at compile time and killed the if
:). In C if connect all optimizations it will do the same. Some languages know how to optimize well.
I’m not going to get into the question of logic ports that is too low, but it is only manipulation of existing data in the processor (it was put there before), as already said before, the condition will generate a value in one of flags processor which does not cease to be a register, and a value is changed in the PC
(IP
for some), then the execution continues at the address of the memory that is marked on that register.
For being something more difficult for most if you have some point not understood warn, I can improve the answer according to the need.
This reply would help you?
– Luiz Augusto
@Luizaugusto I’m talking as an if it works internally, as if "magic" happens
– NinjaTroll