Computer architecture
Before we learn to program
I’m going to start sharing what I know about writing code and developing software, but first I wish to start with sharing some of what happens under the hood.
I am kind of pedantic about things like this, but I am a member of the “No Black Boxes” club. I don’t like things to be hidden. I prefer to know exactly what is going on in my equipment, my electronics, and even in my programs. Though, I do realize I don’t completely care how a given compiler actually works, just that it does its job.
Black Boxes refers to something my father-in-law taught me about electronics and was prevalent when I first began learning such things. Many techs or engineers would be asked to provide some kind of electronic device that did a specific task. They would design it, test it, and package it into a black phenolic plastic box that was uber-common back then. You can still by them on Amazon. Then you gave your “customer” the box and explained the “goes in’s and goes out’s”. The customer had no idea how things worked inside the black box. It just did its job.
That’s all cool and such, but I don’t like my programs to operate like that. The issue with computers in general is that there are a lot of “undefined behaviors”. Programs can compile correctly, but still not act correctly. Therefore, it is a good idea to know what is going on under the hood.
While I plan to start with C, it is better if I explain how a CPU works; not in a technical way, just a common explanation.
Apart from CPU’s being small blocks of silicon with wires attached, I’m going to talk about architecture. The things that are important to a programmer. If you want the TLDR version, you can find everything here.
Most modern CPU’s conform to an x86 standard. This comes from the earlier 8086 chips used in the original IBM PC/XT and other clones. While what I am going to explain are the 8-bit and 16-bit registers, later versions added an ‘E’ in front ( EAX instead of AX ) for 32-bit CPU’s. Currently, we are in the x86-64 CPU chipsets (RAX).
I’m not going to cover a lot of details about programming. This won’t be an assembly primer. But, hopefully, it’ll be just enough so that you will understand that what you write in code becomes something else entirely inside the CPU.
CPU’s have two basic parts, the control unit and the arithmetic logic unit. Nearly all of today’s x86 CPU’s also include a floating point unit that was an additional chip in the earlier models. These are all connected via buses or sets of wires that are similar to the size of the instruction set ( but not exactly ). For example, if I remember right, 8-bit machines had a bus of 20 wires ( 8 x 8 + 4 ). The extra wires were control wires and the 8 x 8 carried instructions and memory addresses back and forth.
Programmers used many of the registers in the CPU to make it do something (anything?). You moved data and addresses into and out of registers and then called the CPU to act upon those registers. There are four general purpose registers: AX, BX, CX, and DX. There is also an instruction pointer register that pointed to the memory address of the next instruction: IP. There was also a stack for temporary data to be pushed and popped from as needed: SP and SS registers. There were also registers for the memory address of a destination: DI and a memory source address: SI.
Programmers loaded these registers with values and then called an instruction. There were also a large set of flags that could be checked for errors, math overflows ( going larger that the biggest number ), and other CPU status items.
Just remember that as CPU’s became bigger ( 32 and then 64 bit ), all of these registers added and ‘E’ and later an ‘R’ in front. However, for efficiency, a programmer sometimes would drop a larger register back to a smaller one to save time and memory ( using EAX instead of RAX ).
So, when you type something in C like this:
#include <stdio.h>
int main( void ){
printf( "Hello World!\n" );
return 0;
}
Or, like this in Java:
public class Main {
public static void main( String[] args ){
System.out.println( "Hello World" );
}
}
Remember that inside the CPU, nothing looks at all like you wrote it. Everything gets transferred to a representation that utilizes the registers, flags, memory addresses, and CPU instructions to carry out what you asked, whether through compiled or interpreted code, or from a runtime like the Java Virtual Machine. Computers are stupid. They will do EXACTLY what you tell them, even if you didn’t intend it that way. You, the programmer are always in control.
No tests. No exams. This is the last time I’ll mention any of this. Next time, we get the fun stuff. Happy coding!