Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does the processor handle conditions?

So, SUPER low-level what does an IF() look like, how is it handled by an x86 processor?

like image 949
UnkwnTech Avatar asked Mar 25 '09 19:03

UnkwnTech


People also ask

How does the processor perform its function?

CPU Operations The four primary functions of a processor are fetch, decode, execute and write back. Fetch- is the operation which receives instructions from program memory from a systems RAM. Execute- is where the operation is performed. Each part of the CPU that is needed is activated to carry out the instructions.

How does a CPU work short answer?

The CPU is an electronic machine that works on a list of computer things to do, called instructions. It reads the list of instructions and runs (executes) each one in order. A list of instructions that a CPU can run is a computer program. The clock rate, or speed of a CPU's internal parts, is measured in hertz (Hz).

How do you know if a processor is good?

Benchmarks. When buying a new PC, you can check the CPU's name to get its age and approximate performance level. The blurb should also tell you the clock speed and whether it's a dual core or quad-core chip. More GHz and more cores are always better, though a dual-core chip can still be faster than a quad-core.

What are the 3 components of CPU and their functions?

The three logical units that make up the central processing unit are the arithmetic and logic unit (ALU), main storage, and the control unit. Main storage retains active programs and data. It is relatively expensive, so secondary storage is used to store programs and data until they are needed in main storage.


4 Answers

The processor has "Branch if" instructions that when a certain condition is met it branches, and otherwise it continues on to the next instruction.

So

if(A)
{
    dosomething;
}

would become

load A into register 0
if the zero flag is set (ie, register 0 contains 0x00) then jump to endcondition)
dosomething
endcondition:

More complex conditions ( if(A || B && C) ) become a sequence of instructions that leaves a register in a 0 or non zero state, so the branchif instruction can jump or not jump based on the conditional flags.

There are many conditional flags (zero, carry, negative, overflow, etc), and some branchif instructions also operate on more complex conditions (ie, it might actually check to see if a register is equal to another register, rather than simply looking at flags). Each architecture is different and makes tradeoffs so the instruction set is complete, but also speedy and compact.

As moocha points out in the comments, some architectures allow you to apply a conditional to some, many, or even all instructions, so you might not only have 'branch if' instructions, but also 'and if', 'add if', 'move if' etc.

The x86 is very, very, very complex beyond this simple explanation once you get into pipelining, out of order execution, caching, microcode, and all the other advanced topics. For most purposes the above explanation is sufficient. If you're writing a hand crafted very, very tightly wound algorithm, though, you'll have to take these things into account for maximum performance and throughput.

That's a topic for another question though...

-Adam

like image 174
Adam Davis Avatar answered Oct 05 '22 23:10

Adam Davis


It's fairly easy to use the output of a C compiler (use the -S switch on gcc) to see what output a given snippet of C will generate when compiled. Be careful when using optimisation on toy programs though. If you're not careful the optimiser will often optimise away conditionals that will always go one way or another (see this article on microbenchmarks for a more detailed explanation).

For example, a trivial C program:

#include <stdio.h>

int main (int argc, char **argv) {
    int ii = 10;
    int jj = 20;
    if (jj > ii) {
        puts ("jj > ii \n");
    }
    return 0;
}

compiles to the following assembly language:

    .file   "foo.c"
    .section    .rodata
.LC0:
    .string "jj > ii \n"
    .text
.globl main
    .type   main, @function
main:
    leal    4(%esp), %ecx
    andl    $-16, %esp
    pushl   -4(%ecx)
    pushl   %ebp
    movl    %esp, %ebp
    pushl   %ecx
    subl    $20, %esp
    movl    $10, -8(%ebp)
    movl    $20, -12(%ebp)
    movl    -12(%ebp), %eax
    cmpl    -8(%ebp), %eax
    jle .L2
    movl    $.LC0, (%esp)
    call    puts
.L2:
    movl    $0, %eax
    addl    $20, %esp
    popl    %ecx
    popl    %ebp
    leal    -4(%ecx), %esp
    ret
    .size   main, .-main
    .ident  "GCC: (Ubuntu 4.3.2-1ubuntu12) 4.3.2"
    .section    .note.GNU-stack,"",@progbits

For a brief dissection of what's going on:

  • The first section (.rodata) declares a constant with the string 'jj > ii \n')

  • The second section is initialising the contents of the ii and jj variables on the stack.

  • The bit from cmpl -8(%ebp), %eax is doing the actual comparison; the jle instruction is skipping over the call to 'puts', which is effectively the logic of the 'if' statement reversed.

  • After the label '.L2' the system is tidying up the top of the stack and returning from the call.

like image 28
ConcernedOfTunbridgeWells Avatar answered Oct 05 '22 23:10

ConcernedOfTunbridgeWells


It's a branch instruction, dependent on the specific machine architecture. It figures out how to set up a memory location or register to test for a specific low-level condition - like branch-if-not-equal or branch-if-not-zero, ... -- does that test then jumps (or doesn't if the condition fails) to another part of memory. Obviously if you have a complex condition it may need to do evaluate many different conditions and may involve several branch instructions.

like image 31
tvanfosson Avatar answered Oct 05 '22 23:10

tvanfosson


Generally the CPU has what is called an Instruction register, which holds the memory address of the current machine language opcode to be executed next... and numerous other registers to hold data.

Generally, after the cpu executes each opcode in the the instruction register, it simply increments it by one to move to the next position in memory which should have the next opcode in the compiled program application.

One opcode (actually there are probably several), however allows the cpu to "Branch", by "comparing" the values in two other cpu registers, and if one is greater than the other, it copies one memory address into the instruction register, whereas if the other is the largest, it copies a second, different memory address into the instruction register.

That's about as "low" level as it can be put it w/o talking about relays and transistors...

like image 45
Charles Bretana Avatar answered Oct 06 '22 01:10

Charles Bretana