Summary
Computers can only handle complex tasks, such as web browsing, simulation or data processing as these tasks can be broken down into a series of very simple instructions. One of the greatest successes of computer science is the discovery of universal computing machines. Relatively limited instruction sets allow for extremely complicated processes to be computed. Most of the modern development in making new processing chips is in making this process more efficient (in speed, or sometimes power consumption).
The early days of programming required programmers to write their software directly in the instruction sets required by these computers. Nowadays, we are able to write programs using a high level language (e.g. Python, Julia etc.). The reason that computers are able to execute these programs is that we have other software which can convert our high level programs, written in (hopefully) human-readable text, into the lower level instructions that the CPU can execute. These programs that convert code are called compilers. These are often extremely complicated bits of software with many stages. Some languages (i.e. Python), directly run the higher level source code by interpreting the high level code line by line, converting the program on the fly into the relevant lower level instructions. In the next section, we will talk about how this process works, along with the factors that are relevant for performance.