Question:
How do computers carry out "if" statements at the machine level?
RAZR
2010-01-03 00:16:13 UTC
Can anybody help explain or direct me to some resources (books,websites,etc..) on how computers carry out "if" statements at the deep machine level and not from the software point of view?

I have always been curious as to how its able to perform those statements. What does it do? Most books that i have read just touch on the aspect of calculations (full adders, half adders, ALU), truth tables and such but miss the conditional statements. Thank you.
Eight answers:
modchipv12
2010-01-03 00:45:34 UTC
It's done using a combination of CMP or TEST with JUMP IF .



0: MOV EAX, 1337

1: TEST EAX

2: JNZ 5

3: PUSH "The number that was just put into EAX is equal to 0."

4: JMP 6

5: PUSH "The number that was just put into EAX is NOT equal to 0."

6: CALL

7: RETN



Since 1337 is not equal to 0, the message box tells us that it's not equal to 0.



This is what CMP looks like:



0: MOV EAX, 1337

1: MOV EBX, 1337

2: CMP EAX, EBX

3: JNE 5

4: PUSH "The numbers just put into EAX and EBX are equal to each other."

5: JMP 6

6: PUSH "The numbers just put into EAX and EBX are NOT equal to each other."

7: CALL

8: RETN



EAX and EBX are equal to each other since they're both 1337, so the message box tells us that they are in fact equal to each other.



Now let's do a little for loop here: show a message box a specific number of times.



0: MOV EAX, 4

1: PUSH "Message Box says word, yo."

2: CALL

3: DEC EAX

4: TEST EAX

5: JNZ 1

6: RETN



This shows the message box 4 times.



EAX is 4. Show the message box. Change EAX to 3. Check if it is 0. It isn't.

EAX is 3. Show the message box. Change EAX to 2. Check if it is 0. It isn't.

EAX is 2. Show the message box. Change EAX to 1. Check if it is 0. It isn't.

EAX is 1. Show the message box. Change EAX to 0. Check if it is 0. It is. Continue to line 6 and return.



So that's it. Go google for "assembly" (or "asm") now and have fun.



To answer your question about actually carrying these out, it has to do with logic gates. A logic gate is anything (seriously ANYTHING; a device, a marble contraption, etc) that does boolean logic: give one single output depending on two true/false inputs. You know about this, right? An AND logic gate is anything that returns true only if its two inputs are TRUE and TRUE. An XOR logic gate is anything that returns true only if one input is TRUE and the other is FALSE. Etc.



A CPU at the microscopic level does this. Yeah it's microscopic. Everything by AMD and Intel is on a single 45nm die now. AMD/Intel has made the specific arrangement of gates for each instruction for you. A processor is filled with temporary memory locations that keep track of the last CMP or the last TEST or the stack etc. not to mention the ~8 registers like EAX and EBX.



So let's say we have to build the CMP circuit. Because I don't want to spend all night drawing everything out, here's a high-level description: the two inputs are each constantly decremented, and whichever runs out first is smaller. There may be some sort of proprietary technique known only to AMD or Intel that can "weigh" the electricity all at once, but we'll never know for ourselves.



JNZ, JZ, JNE, JE, etc are extremely similar to that. JNZ/JZ would do the same as what I showed you above: just compare the number with 0.



So now you're wondering how the CPU apparently would know how to jump to the right code? Where's the code? The operating system (its kernel, actually, if I recall correctly) takes care of that. The OS passes all instructions to the CPU in a stream. It kind of has to be an instruction interpreter of its own to know where to hold the code and who to give it back to. The kernel decides how much of the program's instructions enters this stream per second / per whatever other time period. Normally, most of the binary file (exe if you're on Windows) is kept in RAM until Windows says it's time to be read again, in which case Windows commands the motherboard to copy it over to the memory controller of the northbridge.



In Jump commands, this is where the CPU actually jumps through.



Alright, so if you want to know how calculations are done, kick back, relax, and look at these:



http://www.youtube.com/watch?v=pP1yTDEtiDE&fmt=18

http://www.youtube.com/watch?v=QoPuEGuGix0

http://www.youtube.com/watch?v=I3JY8sYNZUs

http://www.youtube.com/watch?v=UpCeWWgVIsI



I found a good LBP level that explains base conversion between decimal and binary and how to increment and decrement, but nobody's made a video of it.



So I hope I covered everything. :)
Just Jess
2010-01-03 00:51:52 UTC
An "if" statement is just an extension of boolean logic.



A lot of times, bash programmers will do this

if [ "${HAPPY}" == "Birthday" ]

then

... (do something)

fi



In English, that means "If the string in the variable HAPPY is the same as the string 'Birthday', do something"



But sometimes, if there's only one something, there's a shorthand trick: the double ampersand, which means "logical and".



Logical ANDs work a lot like the bitwise ANDs you're used to at the machine level. That is, if you were adding the numbers 1 and 7, or 1 and 111, you would get

001

+

111

___

001

since the only bits that are the same are the 1 at the very end. Similarly, a logical AND works only if what is on the left hand side is the same as what's on the right hand side.



Now here's the trick: given the above example, I could have added 1 to anything and, with a bitwise AND, gotten either 1 or 0 as a result (1 and 0 is 0, 0 and 0 is 0). I don't even have to test the first two bits; whenever a zero combines with anything, I'll get a zero. So, you can use a bitwise AND as a logical AND provided the argument on the left is zero, and you have an odd integer or zero on the right.



Therefore, that if...then statement earlier can be written like this:



[ "${HAPPY}" == "Birthday" ] && do something



Why? Because the only time the computer will even look at "do something", is if the test on the left side of the logical AND returns true.



In other words, we can turn that around and say that an if statement is simply a special case of a logical AND, which in turn is just a special case of a bitwise AND. The computer simply treats the condition you are testing for as either the number 1 or the number zero. And the only part that needs to be boolean is the condition on the left. If it is zero, what's on the right is ignored, otherwise, it is run.



That can go as low a level as you want. If I have an electric circuit sitting past a transistor, the circuit will only have power if there's enough electricity going through the transistor.
husoski
2010-01-03 02:28:29 UTC
Computers organize their calculations and other processing into units called "instructions". Each instruction is read from memory. A portion of that instruction is an operation code that determines what operations the computer will perform to "execute" that instruction. Instruction is normally sequential, meaning that when one instruction finished, the next instruction immediately follows the previous one in memory.



The 80x86 instructions for a compiler language statement like "C = B + A" might be:

MOV EAX,[Loc_A]

ADD EAX,[Loc_B]

MOV [Loc_C],EAX



These are symbolic instructions, as used in a type of program called an "assembler" which translates human-readable lines into individual computer instructions. The brackets indicate that a memory word is used as an operand. This instruction moves the contents of the memory word labeled Loc_A to the EAX register (for unimportant historiacl reasons, this is the name of the usual "accumulator" register.) The next one adds the contents of the EAX register with the contents of the memory word labeled Loc_B together and stores the sum back into EAX. The third instruction stores the sum into the memory word labeled Loc_C.



To break up the sequential execution of instructions, special instructions called "jumps" or "branches" are used. A jump instruction specifies a new next-instruction address to be used instead of sequentially following the current instruction. Execution "jumps" to the new location. Conditional jump instructions perform that jump only if a certain condition is met. The high-level code for an absolute value calculation: "if a >= 0 then b = a else b = -a" might be implemented as:



MOV AX,[Loc_A]

CMP AX,0

JGE Minus

MOV [Loc_B],AX

JMP Continue

Minus:

NEG AX

MOV [Loc_B], AX

Continue:



The CMP is a compare instruction that sets flags used by a subsequent conditional jump. The JGE instruction jumps to the labeled instruction location if the compare produced a "greater or equal" condition. The JMP instruction is an unconditional jump, which always jumps to the labeled instruction.



At the "deep machine level" sequential instruction execution is usually implemented with an Instruction Address Register (IAR) that specifies the memory address for instruction fetching. This register normally auto-increments after each fetch. A jump instruction simply transfers a new value to the IAR in order to start fetching at a different location for the next instruction.



That's the conceptual model, anyway, and it used to be just that simple in silicon. Modern processors, however have pipelines and instruction prefetch queues, along with multiple instruction units and out-or-order execution. An unexpected jump on such a system requires a lot of clearing-out of prefetched instructions and lookahead calculations. A lot of hardware is dedicated to "branch prediction" logic to try to minimize the number of "unexpected" jumps.
jackie
2016-04-24 09:00:37 UTC
In a basketball game, is important to know how to dunk therefore if you should be a novice or even a professional than you'll need this system https://tr.im/d5N7V to jump much higher and get all the attention from the crowd.

Adam Folker could be the creator of this phenomenal plan Vert Shock.

With Vert Shock you will learn: the best stretching workouts also instantly increase your vertical jump, what sort of shoes to use when attempting to jump high, right getting process to maximize jump level and different sly'hacks'right from the NBA

Therefore, whether you are playing for fun or looking to become a skilled, whether you're seeking to dunk or just become more athletic, you will see how Vert Shock can really allow you to take your game to another location level.
Craig G
2010-01-03 01:00:48 UTC
Modchipv is right, but a little confusing in his presentation.



Basically, there is a machine instruction that says, "jump if register X is zero, nnnn" where nnnn is either a register or an actual address and X is whatever identifiers are used for registers in the particular CPU architecture.



So the usual assembly flow is to subtract something from register X and conditionally jump. If that doesn't answer the question, look up microcode and read everything you can. All modern microprocessors actually operate one level above pure hardware decisions; they interpret microcode which is burned into them in fabrication.
Jim
2010-01-03 02:16:12 UTC
it's done with machine code. you can use an assembler (the direct way) or a compiler to generate machine code. a compiler generates a LOT more code than an assembler, however, there are much more useful I/O and utility and math libraries with compilers.



Assemblers like nasm have one advantage - they generate the tightest code.



It used to be that hand-tuned assembler was the only way to do multimedia drivers. in a few cases it still is done that way I think, where MMX instructions are used. Compilers and newer processor technologies like pipelining combined with other things have actually made hand-optimized assembler a disadvantage. Optimization is now done by the compiler.



you use conditional jump instructions to make branching decisions like an if statement. on intel processors, there are many kinds, and some are duplicates (just renamed for us humans)



a sample of code would be

segment code

;exe header

..start:

mov ax,.data

mov ds,ax

mov ax,.stack

mov ss,ax

mov sp,stacktoporg



cmp al,12

jb abc ;If 0-11

cmp al,13

jne def ;If not equal to 13

abc: mov al,12 ;8 = Unsupported (Reserved)

def: mov bx,2000

mov cx,3000

add cx,bx

mov bl,0

mov cx, 100 ;do this 100 times using loop statement

lupe:

mov al, 2

inc bl

mul bl ;result in ax, multiplies by al

loop lupe

segment ends

segment stack

resb 64

stacktop:

segment ends

segment data

segment ends





there is jc (jump on carry) jb (jump if below), ja (jump if above) jae (jump if above or equal), jne (jump if not equal) if memory serves me right. in order to use a conditional jump, the flags register must have been previously set by a compare (cmp) or some other operation such as an add (which may trigger the carry flag and/or overflow flag). there is also jnz (jump if not zero) and related similar instructions from that, jnc (jump if not carry).



you can save/restore the flags to the stack with pushf and popf.



there are memory copy instructions like stosb.







if you want the actual list of intel processor instructions, please refer to the processor manuals that I gave the link to. enjoy.
farrer
2016-10-06 12:10:50 UTC
The definition of happiness is "being content textile with one's self." It doesn't count number how some distance up the ladder-of-existence we've climbed, extremely its how we taken care of others as we make the confusing climb to the real.
Barbara
2017-02-27 23:14:58 UTC
1


This content was originally posted on Y! Answers, a Q&A website that shut down in 2021.
Loading...