I don’t remember when I first discovered the beautiful clarity of Boolean logic. I do remember that I was fascinated by it. It was incredible to realize that you could take a few simple circuits and replicate them over and over again and end up with something as complex as a computer central processing unit. Furthermore, you could take those CPUs and cluster them together to produce an even more capable system. The way these components nested was somewhat like an onion, with layer embedded inside layer. This was about the time that I began developing an appreciation for the software side of things.
At the simplest level the operations of a typical CPU can be broken down into around twenty operations. There are often a lot of variations on those basic operations such that a typical eight bit microprocessor might have well over a hundred instructions. By the time you get to a modern sixty four bit processor there are quite a bit more. The difference is, very few people even bother to learn machine language for modern processors any more. It is too complicated to try to keep straight in your mind.
So, how do we program computers? We write programs in higher level languages that are subsequently executed on software that is resident in that machine. There are two main approaches to executing these higher level programs. The first way is to compile or translate them into the machine language of the processor so that they can run immediately without further processing. The second is to examine the high level program expression by expression interpreting their meaning interactively. Historically this was seen as a much slower process but it had the advantage of being a lot easier to debut.
There has developed a third approach to executing higher level programs. They are compiled to an intermediate form, called byte code. This byte code is a kind of abstract machine language. The abstract machine is implemented as a program on each type of physical computer that we might want to run programs on. This is called a Virtual Machine or VM. Unlike a physical processor which has a different machine language for each type of physical processor, the VM executes the same byte code on every physical computer that it runs on. This allows us to run the precompiled byte codes on any virtual machine we care to.
Physical processors have gotten bigger and faster and more capable over the years. Interpreters used to be considered painfully slow. Now for all but the most computationally intensive problems, interpreters exhibit perfectly acceptable performance. They are typically a lot easier to write code for. It has also turned out that any given language will have a formal definition that determines how a program written in that language should perform. There way be numerous implementation of that programming language to give the programmer a wide variety of execution options. For instance, the programmer might develop the program using an interpreter, compile it to machine code for execution on an embedded processor, and byte code compile it for distribution across various VMs that implement the byte code interpreter. All three approaches implement the same language just in three different ways.
Sweet dreams, don’t forget to tell the ones you love that you love them, and most important of all, be kind.