It's practically easy to implement a nice-looking hardware-rendered graphics world in a computer program by using the latest tools such as the DirectX and OpenGL APIs. Many people are fine with just learning a 3D graphics API functions and using that knowledge to render 3D worlds on the screen of their computers. I'm not sure about you but I personally despise that kind of ignorance.

Many programmers will state that it is enough to just know C/C++, acknowledging that it is the fastest and more efficient way to program these days, "hey, that's what high-level programming is all about, why re-invent the wheel?", they say. In my opinion this has nothing to do with reinventing anything and I believe there is just pure joy in knowing how stuff works.

In programming world, knowledge is very important and if you believe otherwise you shouldn't be doing this in the first place. If you are a serious programmer, in many cases, the low-level computer knowledge can be quite helpful. The tutorials and information presented to you here on this web-site have a goal of exploring the complexity of the machine and they also work well as a self-discovery for myself, as I am still learning these things.

No matter how much knowledge you possess, there are always new things to learn and understand. Many of the things presented here come from the self-taught knowledge, so if you are more knowledgeable than me about the many topics presented here, or have more details on the subject, then please send me corrections and/or more information at greg.sidelnikov@gmail.com

In this whole section entitled "Know the Machine", as opposed to any other section presented at this site, the "tutorials" consist of pure information and serve to expand the minds of anybody who sets themselves on the path of exploring computers.

At first, the information in consequent parts might seem a little intermediate to an experienced programmer, but it lies here to build a foundation for a more complex knowledge about computers and how they work; I just don't feel like skipping any fundamental details to avoid confusion in the later parts of the text.

I don't try to explain one topic in detail. At first, I will explain the whole big thing as it is and as you read, the complexity of information will be consequently increased and focused on the important parts. So, gradually we will get to the point of what we do need to know, leaving all of the unnecessary content behind. Ultimately the pieces of information will fall together.

So, let's begin our prolonged journey.... [edited:] But before we do, let me mention that these tutorials will drown you in pure knowledge and information as we descend deeply into the dark halls of the CPU dungeons without a rational reason of wanting to come back.

What do computers (computer processors) think like?

How do computers think? Can computers think? Computers, being built by human beings think in the exact same way as any other human being; yes that's including me and you, and there is nothing you can do about it. This might sound vague to the many, but really, have you ever had a paradoxical thought of how you think yourself? What kind of decisions do you make

Let me tell you, a big part of programming is about making decisions, and you as a programmer are responsible for the subsequent flow of these decisions. You make the machine accomplish tasks by giving it commands, which are usually functions and statements, if you're a C/C++ programmer (but these functions and statements usually hide the real underlying processes that are also crucial to understand if you are serious about it).

If you're programming at a lower level, you might as well be dealing with the Assembly Language instructions passed to the CPU as the aforementioned commands. It is more apparent at a lower level but no matter what you do with your program, the real raw code will always come down to dealing with two alternatives (when it comes to making a decision) and picking one of them to follow, and if you delve deeper into how you think yourself, you will also realize that this is a very similar way of how your own mind works.

An interesting fact to remember is that there are never 3 or more decisions created at a time, as it might at first seem. All decisions are binary in nature so what might seem as a big complex decision is nothing more than a series of a Yes or No decisions clustered together.

The consequent decisions of your mind follow similar stages as decisions of a computer program; everything's binary. The main difference, however, between your mind and the CPU is that the CPU has no consciousness. But if you think about it, humans don't either.

Consciousness is a heavily studied topic in science, but for now let's concentrate on our unaware friend - the computer. So how does it work? To understand how anything works at all, we need to understand the rules and the underlying processes of the thing you are trying to understand. Now we have to ask ourselves: what are these rules and processes when we think of computers? We will get there eventually, but first, a little history on the subject.

All of the computers in the world have what is called a CPU (Central Processing Unit). It's the core, the main operating room if you will, of a computer. To the majority of population here on Earth it is mainly known as the processor.

There's been a number of advancements in the previous years in the world of microprocessors, particularly inside a company known as Intel. Intel has been producing CPU's since the times I haven't even been born yet which in turn accommodates for over twenty and one years and as not a big of a surprise they have pretty much remained to be the processing god of the computer industry ever since. In 1971 Intel introduced its first microprocessor named Intel 4004. The 4004 was a 4-bit processor, meaning that it could operate on data of 4 bits long at a time. The 4004 microprocessor could only add and subtract numbers.

Intel 4004

The breakthrough of this particular chip was that all of the transistors were conveniently residing on one chip, as opposed to any previously assembled CPU (very primitive at that time). Transistors in a CPU act as electrically charged switches which either hold an electric current or don't.

This is where the concept of RAM (Random Access Memory) -- or practically any type of memory really -- comes from but this will be explained in time. As the technology advanced, in 1974 Intel introduced its first 8-bit processor, the Intel 8080.

Intel 8080

This processor was operating with 8 bits at a time and had many machine instructions that it could execute.

What's a machine instruction?

As a small deviation from computer processor history, I want to use this space to explain what a machine instruction is. A machine instruction is the basis to the concept of programming.

Remember that the computer has no other means to represent data other than by using 0s and 1s embedded into the CPU core by transistors. So an electric charge is used to create a special number consisting of 0s and 1s which acts as a command sent into the CPU. The CPU identifies this number and by using this instruction number and the data residing in the special placeholders called registers, also on the CPU, it creates a series of electric chain reactions which when complete, return a result, regularly back into one of the registers. So then you can use the name of a register to get the result and pass it on to the following instructions.

The programmer is responsible for knowing what these instructions do and into which registers a result will be returned. This is the basic formula of what's happening. Of course there are many more details to this process.

For example, as the instructions run in a consequent order it is common for them to modify (or act upon what's stored in) specific values called flags which reside in a special register called the flags register. On the modern computers this register is 32 bits long (and it's called EFLAGS), so there are virtually 32 flags alltogether resided on the chip. Apparently, a flag bit can only hold a value of one or zero and has a specific meaning within the CPU.

So you might be wondering, that a programmer has to know all of these confusing long binary numbers to execute an instruction into the CPU. Not exactly so.

Although the CPU might only understand binary numbers, there exists a slightly less mundane system of representing these instructions. The Assembly Language serves as a little bridge between all of the 0s & 1s and the actual representation of an instruction.

The Assembly Language gives the programmer a representation of the CPU instruction set in an easier manner: an instruction is actually a shorthand version of all of the long binary numbers that would be practically impossible to remember unless you had much time on your hands, which I'm sure nobody does. Let's take a look at the following Assembly Language instruction.

push bx ; pushes the bx register onto the register stack

The instruction push bx is actually a binary number 01010011 or 0x53h in the hexadecimal (base 16) number system and is a much more convenient way of telling the CPU about what you want to accomplish

In this example, the push instruction "pushes" the BX register onto the register stack. There are many reasons a programmer would want to do this but for now we are concerned with how it all fits together. The push instruction can also be used with some of the other register, such as the AX register, the binary number which represents push ax is a little different but to the programmer it doesn't really matter (unless you're programming the assembler itself).

Obviously there are many more instructions that the CPU understands and alltogether they are called the instruction set. In the Assembly Language the process of putting an instruction into something that computer actually understands (such as the binary representation of the instruction and data) is called "assembling" your program, and is done with a not so little help of yet another program called the assembler. Many people mix up the definitions of these terms foolishly naming the Assembly Language - assembler, which is really not a directly correct thing to say.

Note that in the C/C++ environment, this process of "assembling" a program is usually referred to as "compiling" (or building) your program, and a C or C++ command (or function) is even clearer to the programmer than an Assembly Language instruction (which would be as close to the CPU as it can get without losing common sanity).

This information wouldn't be as useful without a real-programming-life example. So, I will finalize the discussion about machine instructions by showing you a tiny Assembly Language code clip vs. C code.

Here is the Assembly code featuring some of the other instructions, particularly the mov and the rep instructions. Note that the assembly code is actually inside of a C function, the assembly part is resided only inside the brackets __asm { here }, highlighted in yellow. (Commonly, of course, an Assembly program is written within an Assembly Language GDI; I am only showing you it this way because it merely serves as an example).

// This function sets a memory block of size "len" to whatever is
// stored at the specified destination address, faster than a
// standard C-library "memset" function which operates on bytes only.
// This function fills a double word of memory in one shot. This is
// only one of the many ways an Assembly Language program can be used
// in advantage to the C programmer. And there are indeed many...
__inline void fastmemset (const void *dst, const void *src, int len)
{
__asm {
mov ecx, len ;move the dword in len into the ecx register
mov eax, src ;move the source address into the eax register
mov edi, dst ;move the destination address into the edi register
rep stosd ;execute the rep stosd instruction which does all of the
;real dirty work of copying the memory blocks within the CPU
}
}
And here is a piece of a C program, as you can see the code is more readable and understandable to the programmer, however it is not as close to the hardware as the Assembly instructions are:
void PutPixel (video_t *video, int x, int y, color_t *c)
{
byte *screen = (byte *)video->data; // get the screen memory address
screen[x + y * video->pitch] = c->i; // put a pixel value at X and Y pos.
}

This function draws a pixel on the screen by the way. You can actually decipher some of the equations in this code as it is easier to comprehend. However, the point is, in the end this compiles and builds into 0's and 1s anyway, the level of understanding the code is higher but the level of controlling the real raw speed and performance of the CPU is lower than it is in the Assembly Language which is practically identical to "talking" to the machine.

With the modern compiling tools the bridge between these ideas is being shortened, so that there is less need to use the Assembly Language, however it is still a very fundamental thing to know if you are a, should I say, serious programmer. This sums up this short discussion about machine instructions, and back to the history...

Back to History

As you might recall I was talking about the 8080 processor so we will go from there. The 8080 was an 8-bit processor and worked with 8 bits at a time. Today, this processor is obsolete, however it served as a breakthrough in the CPU world.

The 8080 gave birth to a more advanced set of processors. Particularly the 8088 and 8086. These chips were very alike and had the same instruction set. The main difference between them was that the 8088 still worked with 8 bits at a time while the 8086 processor could operate on data containing 16 bits, which is two bytes or a "word" in computer data terms (a word is two bytes paired together).

Consequently Intel has produced microprocessors with ascending advancements based on the 8086 chip architecture. These include: 80286, 80386 and 80486. Further, the Pentium processor (also known as the 80586), Pentium II, Pentium III, and Pentium IV which at this time serves as the current standard in the micro-processing world.

Pentium IV

The difference in speed and performance between 8088 and Pentium IV is tremendous. What could be done back in the mid-70's can now be done hundreds of times faster, and in computer time, it's a really mind-boggling change in performance. The main difference between all of the mentioned models, apart from the performance boost-up, is that every time Intel comes out with a new microprocessor, they always maximize the number of transistors on the chip.

The early 8088 processors had only 6,000 transistors, while a Pentium IV chip has 55,000,000 of them. As you can imagine these transistors are very small in size and their size has been decreasing through the years of microprocessor development. The following is an excerpt from the Intel web-site:

'Like Intel's processors, the fabrication techniques used to produce them have also evolved considerably during the 25 years since the first 8086 chips were rolled out.

In those days, the connections etched into the silicon were about 3 microns wide. Today, Intel's most recent chips have connections that are 90 nanometers in length, and research continues into ever-smaller dimensions'.

This is a picture of a modern (1995-2004) CPU transistor. I won't go any further than this into the history of computer processors as we (as programmers, I assume) need to catch up with how they actually work, and not who (and when) built them...

Actually I just don't have that much time to explain everything, the KTM tutorials should merely make some fundamental points clear, and direct other programmers onto the right path, then you're basically on your own from there on. However, with all that said I still try to be as detailed as possible in my text, there is a lot of information out there and we're only touchnig the tip of a vastly gigantic iceberg.

I also want to point out right now, I don't want the KTM tutorial series have any strong inclination on how the text is structured, there is no particular order in the topics of consequent paragraphs as you might have noticed already, but I try to put things together in an understandable way and explain some fundamental knowledge.

However, this is all just general information. The next part (ktm1) is more technical as you will see. So these tutorials pick up after a strange mannerism technique that i've myself just developed -- so... get used to it! I'm going to generalize some concepts now and we will move on to one of the most fundamental comcepts of programming - computer memory.

Briefly about Storage and Memory Access

So how exactly is anything stored on the CPU chip? This brings us to an explanation of what computer memory is and how it works; actually this is a topic of the next part of the "Know the Machine" series where I explain memory addressing, memory access and more in greater detail, however here I want to write down some memory fundamentals and some hardware specifications. Read this and the following chapter and we will get to understanding memory in greater detail.

So, listen carefully and (try to) remember. As previously concealed, a transistor and a capacitor are paired to create a memory cell which represents a single bit of data. The capacitor holds the bit of information which is a 0 or a 1.

The transistor acts as a switch that lets the control circuitry on the memory chip read the capacitor or change its state. These memory cells are aligned so that it is convenient to read the data in blocks. On a 8-bit processor these blocks are bytes.

On a modern 32-bit processors these blocks are represented as double words (32-bits = 4 bytes = a double word) memory cells. Commonly, there is an input and output pin (the Data Pin) and a few Address Pins alligned in a row on a memory storing device. Let's take a look at the following which is a representation of a RAM (Random Access Memory) chip.

A single instruction is executed after another one in a linear order, unless an instruction commands the process to jump to a different address from the current address. And this is the common flow of a computer program.

To the eyes of a C-language programmer, all of these underlying processes are of course hidden by the compiler, however knowing what's really going on inside could help in certain situations so if you haven't looked into the Assembly Language at all, I would recommend doing so.

There are various books and internet resources on the topic that could expand your knowledge. I would recommend digging out the infamous (and outprinted) Michael Abrash's Graphics Programming Black Book and Jeff Duntemann's Assembly Language Step-by-Step books for that purpose.

As for now, this sums up my discussions of the CPU in this section; I might be able to update this page with even more information in the future.

Also I want to point out that I would like to know what you guys think of this and other tutorials on this page, so by sending me your feedback you will encourage me to write more informational and programming tutorials.

In the following section I will talk about how CPU memory is accessed and what it actually is and how much of it you can play with on a modern CPU and a lot more you should know, so read on...