Beginnings
Modern computers are digital. They rely on transistors, a basic physical building block of electronic circuits, to implement digital logic. It is well known that computers employ a language of 0s and 1s. But why? Where do 0s and 1s originate? How do you get there from transistors?
Prelim
In everyday use, digital has come to mean or symbolize computer technology in general, which is not helpful here. So let's start with some working notions. A digital computer only deals with information in discrete or distinct units that could be listed and/or counted (just like fingers, or digits).
Hover 🔍︎ OR TOUCH
Objects in containers , natural numbers and integers (finite
subsets, technically)
, categories of things
, or their types, or counts, or
attributes are examples of discrete things. Their info is ready to be
conveyed in a form suitable for a digital computer.
Audio is not naturally discrete. It must be first digitized (i.e., converted into a discrete form) before a computer can handle it. The figure depicts the process in principle. Higher sampling rates and more quantization levels lead to better-sounding audio.
Digital logic deals with the discrete yes and no answers, obtained by testing logically [con]joined claims or propositions for truth. It is framed based on constants and variables whose values may be true or false (the logical outcomes of testing propositions). The following figure outlines key ideas.
Hover 🔍︎
A and B must be true to assert Ali is naughty (Ali may not be a boy, or maybe not all boys are naughty, or both). There is an implied yes/no question: Is Ali naughty?
Variables track the logical state of propositions. Truth tables list the outcomes for all possible values. They define a logic to act when the answer is yes. In this case, indicate the logic to test that Ali is naughty. NAND (not-AND) is more useful when no is the active answer.
Z illustrates a typical computer scenario. It involves a zero detection line (Z) that determines, based on a calculation, a course of action in conjunction with a branch request line (BR). If both lines go high, then the calculation must have resulted in zero during a request, which signals a branch away from the main course.
Note that the variables in (c) above change values, unlike those in (b), where they are unlikely to do so, which allows for a logic to react dynamically under varying conditions. In other words, to act conditionally. This subtle difference shows the power of digital logic.
From Physical Device to Code
Physical signals tend to change continuously in the circuitry. When building digital logic, we are not concerned with the smooth variations in some of them. We only care about drastic changes. The discrete physical states corresponding to those changes may encode symbols, at least two (binary), the minimum for serious coding (one is usable, but is quite limiting). The first two numeric digit symbols, 0 and 1, were obvious choices for a computing device.
Hover 🔍︎
To simulate the digital switching actions (marked), a continuous waveform must cross a threshold to be considered to have changed state. The crossover point and whether to assign logical 1 to the high or low side depend on the physical device used to generate the signals. The actions, expressed by physical states HIGH-LOW-HIGH-LOW, may map to 1-0-1-0, or 0-1-0-1 in some cases.
We could track ten distinct state positions to code the familiar ten numeric digits. The resulting physical machine would not do any better or more than a machine based on two states. It would only be more complicated.
The two discrete states of interest in computer circuitry correspond to
when electric signals reach a point where a transistor starts to conduct (ON
state) or the point where it ceases to do so (OFF state). The
binary ON/OFF states may encode a stored value interpreted as a base-2
number, a natural binary code. The base-2 number/code may denote its familiar
decimal value. For example, the code 101 means five if viewed as
a number. That original interpretation gave rise to the term bit for
binary digit. Larger numbers will require more bits, of course.
Bits could also denote other things, such as a character shape, or a selector code for some circuitry, perhaps a data store or pathway, or a distinct sub-circuit (for example, an opcode, short for operation code, to denote an add circuit). Codes also may denote locations in a computer's memory. These selector codes are special. They enable circuitry to locate and access the contents of individual memory stores (hence the term address). They play another crucial role. In some contexts, an address could serve as a logical identifier of the stored item. In all cases, the numeric sense behind bits will always be there when needed due to the base-2 link.
Hover 🔍︎
Characters in Morse (grayed), an older binary coding scheme, and ASCII (ISO 8859-6), a modern one. The last column shows the numeric values when we view ASCII as base-2 numbers. 0s/1s may just as well replace the usual dots and dashes in Morse.
Opcodes for Intel 8080 operations, specified relative to a special internal store where results are collected (accumulator).
An address tells circuitry where to find a storage unit. It also represents the stored items (e.g., the first address, location 65025 numerically, denotes 'A').
Fundamentally, 0s and 1s serve as a standard format to keep information and operations, and therefore, to store them both in the same memory and process them in the same ways, which simplifies the machine tremendously.
Builders could create a binary coding scheme to describe the switching state of key transistors. With a bit more circuitry, it can also instruct the device to assume an operational position by specifying the ON/OFF states those transistors should take. Alternatively, it could prompt a circuit to tell its current switching settings (perhaps to decide how to instruct it next). In other words, a binary-coded language, specific to the circuitry, naturally arises to communicate with the device. Thus, binary codes could also help manage the state, in effect, run the machine, not just serve to store and process data.
Moreover, the two distinct states of logical truth and falsehood may be coded by 1 and 0. Consequently, one may devise logic based on 0s and 1s to manipulate binary codes and hence create a logical binary state. For example, logical operations may transform binary codes to add numbers. The figure, next, illustrates their use to obtain a sum of integers in base-2. This kind of logic is described as digital since it only deals with distinct values. Processing binary codes in more intricate ways requires complex logic and, thus, more transistors.
Hover 🔍︎
To add, a sequence of operations is applied bitwise (at the bit level). Four bits are required to hold the sum.
After a first round, the sequence may repeat zero or more times (in this case, once). XOR logic yields an answer when the shift results in all zeros.
A computer gets into trouble when a shift discards a 1 (details beyond this discussion). It is easy to obtain the correct sum if it only occurs at the end.
To sum up, a modern computer employs transistors as elementary 2-state switches to create a physical basis for binary coding. The states behind the coding stem from ON and OFF switching actions. They also underpin a language that enables the machine to communicate and to set its state. Binary codes, in turn, form a basis for expressing a simplified truth-based version of Boolean logic (one that focuses on the values true and false, the outcomes of testing propositions). A binary state grounded in Boolean logic is essentially what gives a computer its power.
Operations and Operands: The True Language of Computers
While the switching states of transistors do underlie a language of 0s and 1s, a modern computer is a complex machine. It is composed of thousands of specialized electronic circuits that contain up to hundreds of millions of transistors. Its logical state may not obviously relate to that of individual transistors (but it does trace back there, of course). Also, the logical state itself is too primitive and too detailed for direct use in practice.
Therefore, a binary machine language is constructed on top of those physical switching and logical states, to work, by design, at a level meaningful to its users. It typically provides a way to specify operations, called ops for short, and their operands. Binary codes for circuits that perform ops and coded operands, or codes for circuit parts that store and transfer them around, are assembled in specific ways to form a machine instruction. The instruction is then a binary coding of a command that the machine can run. Bits that encode the ops and operands cause some transistors, eventually, to take on the ON/OFF states needed to execute the instruction.
Hover 🔍︎
To add 5 to an operand in a store (labeled CX) and put the result in another store (AX), a user may consult some code tables to put together (assemble) a machine instruction. The codes assigned to operations and other machine resources, such as operand stores, reflect details specific to the machine and the coding choices made by its designers.
Instructions may be combined in various ways to create a machine code that could synthesize higher operations. Scheduling instructions to get the machine to perform tasks was perhaps what gave rise to the terms program and programming.
Hover 🔍︎
The figure shows the 0s and 1s of a real RISC-V instruction (logical and physical ones are not), the last one in a machine code program that flips the signs of integers in an array stored in memory. Bits from machine language obscure those of transistors and Boolean logic, where they originate.
Machine language creates an abstraction layer that hides details of the machine's design and implementation from its users. It abstracts physical transistor states into usable instructions. Lower 0s and 1s are for machine builders. Occasionally, a bit in machine language maps directly to a logical one, which, in turn, maps to a physical bit.
Assembling machine code by hand is a simple but tedious task that a machine can perform. Users may express code in a less cryptic notation that an assembler program can process. The resulting language was relatively easier to work with than bare 0s and 1s. It freed users to focus on operations and operands. Programming systems of all types, and all levels above machine code, seek to facilitate communicating that information in terms more meaningful to humans and the problems they are trying to solve.
Hover 🔍︎
The relatively friendlier assembly language conveys operation and operand information clearly. However, it would also be specific to the machine since it merely describes its instructions and conventions.
To sum up, machine language, the circuitry-specific language of ops and operands, is the language of 0s and 1s that users (programmers and users of their programs) face or experience in some way, shape, or form. It is the basis of a binary code at the machine level. Assembly notation is just a convenient shorthand for that language, and is thus said to be low-level as well.
In Summary
A breakthrough feature of the modern computer is that it utilizes binary coding that a) may be transformed by rules of logic and b) maps to simple physical switching devices, leading to relatively simple hardware.
So, to answer the questions posed at the beginning. The language of 0s and 1s associated with modern computers, most likely the one depicted in popular culture, is machine language or code, founded on a logical state generated by the 0s and 1s of physical switching devices, mainly transistors, for now.
Any physical switch would do, but the transistor was transformative (see the Spectrum magazine link). It is highly reliable, tiny in both size and cost, especially the modern ones. It enabled the faster, more logically complex computing machines of today, and continues to do so as of this writing.
Hover 🔍︎ + Click
Three key ingredients make up modern computers: physical ON/OFF switches, binary coding, and a true/false switching version of Boolean logic, where a variable represents testing a logical proposition for truth rather than the proposition itself.