Modern computers share many theoretical similarities with the Turing Machine, but in practice they are much more advanced. In this section, we’ll discuss how a modern computer is able to run programs we’ve written in a high-level programming language like Java or Python.
A programming language, along with the associated compiler or interpreter, is a complete set of tools to write and translate instructions written in that language into the binary code that a computer’s central processing unit (CPU) can natively execute.
Both Java and Python do this by producing an intermediate representation (byte code) then translating that to machine code. In Java’s case this byte code is saved as a class
file, but usually the Python interpreter does not store the byte code.
Computer central processing units (CPU) exclusively run machine code.
Learning to program requires some basic understanding of how a computer works. In the most basic sense, a computer has a large amount of memory connected to a central processing unit (CPU). The memory consists of many bytes of data, each containing eight binary values (e.g. 01001101).
The memory itself is split into various regions, with different regions storing the machine code instructions that make up a program and the data that the program is operating on.
The CPU contains enough circuitry to interpret the instructions it is given and perform the requested mathematical and logical operations on the data provided.
Consider a single line of code in a program:
z = 5 + 7
In most languages, a line similar to this will instruct the computer add the values of 5 and 7 and save the value into a variable named z
, which will be stored in some location in memory. In a machine language, this single line of code may be actually require different instructions to complete. The table below shows one possible interpretation of that line of code into machine language.
Instruction | Meaning |
---|---|
LVal eax, 0x01A0 |
Load the value found at memory loc 0x01A0 into CPU register eax This is where 5 is stored |
LVal ebx, 0x01A8 |
Load the value found at memory loc 0x01A8 into CPU register ebx This is where 7 is stored |
Add eax, ebx |
Add the values in CPU registers eax and ebx together and store the result back into eax |
Mov eax, 0x01B0 |
Move the value in CPU register eax to memory location 0x01B0 This is where the variable z is stored |
Machine language is pretty ugly, but this is really how a CPU functions. Thankfully, we have many higher-level programming languages available, such as Java and Python, so we usually don’t have to write code directly in machine language.
Estimating Program State
From this, we can come up with a pretty powerful abstraction that represents how a computer works. In programming, an abstraction is a simplified model of a complex system, keeping only the most important details to make using the model easy.
In our abstract model of a computer, we see that a program consists of an ordered list of instructions to be executed, and memory is a set of labelled boxes that can store any data our program requires. We also have a pointer that keeps track of which instruction the computer is currently executing. The list of instructions, the instruction pointer, and the memory combined all make up a program’s state when it is running on a computer. Tools such as Python Tutor or Java Tutor use a model very similar to this to help us understand how our programs actually work.