Python is a programming language used to write programs or set of instructions for a computer. Before jumping directly into learning how to program a computer, it is useful to clarify what a computer is, how it works, and how we can instruct it to perform a specific task.

A good starting point about understanding computers is knowing that although computers process information differently from humans, we can draw parallels between the two processes. For instance, if the only language you understand is English, you will find it challenging to process the meaning of a text written in another language, say Swahili. For your brain to process the information, it must be provided in a representation that you can comprehend.

Visual actions are something people can understand even if they don't speak the same language. It's another representation that humans can understand apart from language. Similarly, computers can work with information when delivered in a representation that they can "understand".

However, saying computers understand information seems a bit odd. Do you think computers really understand information they are provided?

Saying that computers understand the information is a bit like saying light switches understand that they are switching off or switching on the lights. But for the sake of convenience, we will continue using the term. When we say computers understand information, you can think of it as the computer knows what's to do with the information.

Representation

Which form of representation do you think, computers can understand?

The representation that a computer understands is usually in the form of ones and zeroes. Everything on a computer that you see is first expressed in the form of ones and zeroes for the computer to process it. And then the computer represents it back to a representation that you can understand. That's how computing works, in a nutshell.

Can you name a couple of things that you see on a computer?

You can see a bunch of text and images on a browser. You can watch cat videos and listen to your favorite music on the computer. All of these are represented in ones and zeroes for the computer to work with them.

To understand how computers work, we first need to understand how we can represent texts, images, and sounds in the form of zeroes and ones. However, even before that, we need to start with numbers and understand how computers process numbers. Let's take a look.

Representation of numbers

Why do you think humans invented numbers?

Numbers are universal to all human beings. Every human, irrespective of what language they speak, counts things using numbers. Researchers may have different opinions about when humans invented the numbers. However, they generally tend to agree on the earliest utility of numbers: Counting. Let's take a look at how the current method of counting numbers came into existence.

Early Number Systems

The early humans needed a tool to count their possessions, animals in a flock, or members in a tribe, and thus the numbers came into being. To communicate the amount of the object, they could draw the same object that many times. These drawings are called pictographs,  a pictorial symbol for a word or phrase.

For instance, figure 1 represents a pictograph of 5 hens.

Five Hens
Figure 1: Pictograph of Hens

Eventually, drawing multiple instances of the same object became cumbersome. They switched over to drawing one instance of the object while representing its quantity by lines. These were tally marks.

Figure 2: Tally marks representing five hens
Figure 2: Tally marks representing five hens

Figure 2 represents five hens using tally marks using a single pictograph of a hen. The number of lines represents the amount of the object. This system was useful for keeping small quantities but for larger quantities proved to be cumbersome.

As early civilizations developed, they came up with different ways of writing down numbers. Many of these systems, including Greek, Egyptian, and Hebrew numerals, were essentially extensions of tally marks. These systems denoted new symbols to represent a higher magnitude of value.

In Egypt, for instance, a knot on the rope or coiled rope represented 100, while two knots represented 500. These pictorial symbols are referred to as hieroglyphs. Figure 3 shows some of the hieroglyphs and their meaning and the value of the number they represented in the Egyptian Numbering system.

Figure 3: Egyptian Numbering System

In the Egyptian numbering system, each symbol was repeated as many times necessary. Then all were added to get the number. This type of number system is called an additive system.

An additive system is one in which the number represented by a particular set of numerals is simply the sum of the numerals' values. The Egyptian System is considered the first additive system. The order is irrelevant for the numerals.

In figure 4, we represent the number 3212 using the Egyptian numbering system.

Figure 4: The number 3212 in the Egyptian numbering system

What number does the hieroglyph in below figure represent? Figure 4a: Three sticks, two heel bones, three coiled ropes and 5 lotus flowers

  1. 5323
  2. 7523
  3. 6743
  4. 5843

The representation of numbers in the additive system, too, was cumbersome for many numbers. Therefore, the Romans improved the overall system by adding another rule.

If the symbol appearing is smaller than the previous, it should be subtracted rather than added.

Let's look at the Roman numeral system.

Roman Numeral System

To understand the Roman Numerals, let's get familiar with some of its numerals. Table 1 shows some of the symbols from the Roman Numerals Systems.

Table 1: Roman Numerals
Number Roman
1 I
2 II
4 IV
5 V
7 VII
9 IX
10 X
12 XII
50 L
100 C
500 D

Roman numerals are not a purely additive number system. Roman numerals are usually written in order, from largest to smallest and from left to right. More than three identical symbols never appear in a row. Instead, a system to substraction is used.

For instance,
$$
Three = I + I + I = III \\
Four = V - I = IV \\
Eight = V + I + I + I = VIII \\
Nine = X - I = IX
$$

We can write larger numbers using the Roman System while keeping two rules in mind:

When a symbol appears after a larger (or equal) symbol, it is added
$$
VI = V + I = 5 + 1 = 6
$$

$$
CXX = C + X + X = 100 + 10 + 10 = 120
$$

If the symbol appears before a larger symbol, it is subtracted

$$
IV = V − I = 5 − 1 = 4
$$

$$
IX = X − I = 10 − 1 = 9
$$

Let' take the $DXLVII$ as an example.

  • $D$ is larger than $X$, therefore add 500

$$
D = 500
$$

  • The next numeral, $X$, is smaller than $L$. Therefore we will take both of them together and subtract $X$ from $L$:

$$
L - X = 40
$$

  • The next numeral is $V$. Since $I$ is smaller than $V$, we will add the remaining digits to get the value.

$$
VII = 7
$$

Adding all up, we get 547.

What is the value of the following Roman numeral?$$CCCLXVII$$

  1. 547
  2. 367
  3. 333
  4. 387

In contrast to the numbering system, language became sophisticated sooner. Humans could reference objects using a group of symbols or vocalizing rather than drawing objects. There were only a finite number of objects and actions that needed to be communicated in day to day life. However, there was still the problem of numbers. Numbers are infinite.

We cannot assign each number a unique symbol as we will run out of symbols, but the numbers wouldn't end. The additive systems were cumbersome to represent higher numbers.

What do you think humans did to overcome that?

The humans figured out how to use finite symbols to represent all possible numbers in a compact notation.

The humans developed a positional system for numbers. Let's take a look.

Positional Numbering System

The positional system allowed humans to define some unique symbols for numbers and then reuse them by assigning them different values based on their position in the sequence.

In a positional numeral system, we can represent numbers using an ordered set of numerals symbols (called digits). The value of a numeral symbol depends on its position.

Several civilizations developed positional notation independently, including the Babylonians, the Chinese, and the Aztecs.

Around the 7th century, Indian mathematicians perfected the positional number system by introducing $0$ (zero). The positional numeral system, pretty the same as the one which we use today, used only ten unique symbols and could represent any possible number.

The Italian mathematician Leonardo Bonacci, most popularly known as Leonardo of Pisa or Fibonacci, is considered responsible for spreading the use of Indian Numerals throughout Europe after the publication of his book, Liber Abaci in the year 1202. In the book, he notes,

The method of the Indians (Latin Modus Indoram) surpasses any known method to compute. It's a marvelous method. They do their computations using nine figures and the symbol zero.

The symbol 0 could act as a placeholder for the value that represents nothing. The symbol 0 was the missing ingredient which the earlier number system lacked. To understand, let's look at the first ten whole numbers we use today.
$$
\text{First ten whole numbers : }  0, 1, 2, 3, 4, 5, 6,7, 8, 9 ...
$$
Each number is represented by a unique symbol or digit for the first ten whole numbers. After the first ten whole numbers, the number is ten(10) represented by 1 followed by  0.

The digits 1 and 0 representing 10 are not unique symbols anymore. They have already been used to represent a quantity in the first ten whole numbers.  However, when the digit occupies a different position, it represents a unique value. The numbers that follow the first ten digits reuse the unique symbols to represent a different number.
$$
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 ...
$$
Therefore, we can represent any number in this form by reusing only ten unique digits or symbols.

Why do you think there are only ten unique symbols in the number system?

It is very probable that there are only ten unique symbols because humans have ten fingers, which were used for (finger) counting earlier. Because we are using only ten unique symbols, this system is called decimal numeral system.

The decimal numeral system is also called positional notation system with base ten, where base (also called radix) means the number of unique symbols.

You can create different systems by taking different unique symbols or base.

The Babylonians developed a numbering system of base 60 or Sexagesimal numbering system.

Guess where the Babylonian's numbering system is used.

The base 60 is still used, although in a modified form - for measuring time, angles, and geographic coordinates. For instance, each day is made up of 60 minute hours and 60 second minutes.

In computing, we use only a number two digits — 0 and 1. What is the base of such a numbering system?

Since there are only two numerals (0 and 1) to represent every possible number, the base is 2. The base two numbering system is called binary numbering system.

Binary Numbering System

The first binary number is 0, and the next is  1. The decimal number 2 is  10 in binary. Because we have exhausted the number of unique symbols, we will increase the places. Therefore, in binary the next number three is $11$, four is $100$ and five is $101$. The trick is cycling from 0 to 1 and increasing the number of digits on the left-hand side.

Binary numbers are written in the group of four with $0$ padding the leading numbers. For instance, we can write five as $0101$.

Here are numbers 3 - 8 in binary jumbled. Why don't you try to rearrange them in ascending order?

  1. 1000
  2. 0100
  3. 0110
  4. 0101
  5. 0011
  6. 0111

Hexadecimal Numbering System

Another number system often used in computing is the hexadecimal numbering system or base-16 system. The 16 unique numerals, in this case, ranges from 0-9 and A-F.

It might seem a bit confusing to understand how symbols A-F are used in the numbering system.  Table 2  shows the first couple of numbers in the hexadecimal numbering system.

Table 2: First 18 hexadecimal numbers
Decimal Number Hexadecimal Number Decimal Number Hexadecimal Number
0 016 9 916
1 116 10 A16
2 216 11 B16
3 316 12 C16
4 416 13 D16
5 516 14 E16
6 616 15 F16
7 716 16 1016
8 816 17 1116

To differentiate between numbers on different bases, we write in one of the following ways:

  1. add a subscript indicating the base to the end of the number. For example, 716
  2. add prefix indicating the base.  Binary numbers have the prefix 0b while hexadecimal numbers have the prefix 0x.  For instance, 0x7.

As we use the decimal system of numbers in our day-to-day life, we usually skip writing the decimal base. If you see a number without its base specified, you can assume it's in the decimal system.

Table 3: Representation of numbers in different numbering system
Decimal - Base 10 Binary - Base 2 Hexadecimal - Base 16
8 0b1000 0x8
14 0b1110 0xE
103 0b1100111 0x67
143 0b10001111 0x8F
511 0b111111111 0x1FF

Table 3 shows numbers on all three bases. Each of the numbers in a row is the same number represented with a different base. As you can notice, we can represent a number in various base.

What is the value of the number 0x68 in decimal?

  1. 104
  2. 105
  3. 106
  4. 102

In previous quiz, you can easily figure out the value of 0x68 by checking table 3, where the value of 0x67 is shown. However, it's not convenient to refer to some table to figure out the decimal representation.

It makes sense to learn a simple method to convert numbers from different bases into a decimal so that you can understand. Let's understand the positional notation system to understand how to convert numbers from different bases to their decimal representation.

Positional Notation System

In a positional notation system,

  • the place value of each digit position is the value of its digit, multiplied by a power of the base.
  • The power of the base is determined by the digit's position index.

Depending on what position index they occupy, the digit's place value can be determined using the following formulae.
$$
\text{Place value of a digit } = \text{Value of the digit } \times (base)^{index} \tag{1}
$$
The position index starts from 0 for the rightmost digit and increases by one as it moves towards the left. If we add all the place values, we will get the number in the decimal system.

For example, in decimal system, the number 456 can be read as Four hundred and fifty six. We can represent the number 456 in the expanded form as follows:
$$
\begin{aligned}
456 &= 4\times10^2 + 5\times10^1 + 6\times10^0 \\
&= 400 + 50 + 6 \\
\end{aligned}
$$
Here,

  • base of the number is 10
  • 4 occupies the 2nd index therefore it is read as 400
  • 5 in it's 1st index is read as 50
  • 6 in its 0th index is read simply 6.

We can obtain the number represented in the decimal system by adding all its digit's place value.

$$ (a_n...a_0)_b =\sum_{i=0}^{n}{\text{Place Value of } a_i } = \sum_{i=0}^{n}{a \times b^{i}} \tag{2}$$

$$
\text{where a is the place value of the digit, } \text{b is the base &} \text{ i is the position index}
$$

Equation 2 shows the formula to get the expanded decimal system representation of a number. We can represent any number in the expanded form using equation 2.  Here are a couple of numbers in the decimal system and their expanded form.
$$
5_{10}  = 5\times10^0 \\
78_{10} = 7\times10^1 + 8\times10^0 \\
512_{10} = 5 \times 10^2 + 10 \times 10^1 + \times 10^0 \\
$$

What is the place value of 5 in 5123?

  1. 5000
  2. 500
  3. 1000
  4. 100

We can convert a number in a different base to the decimal system by adding the place value of each digit. Let's start with converting binary numbers into decimals.

Here are some numbers in binary and their corresponding representation in decimal.
$$
1000_2 = 1 \times 2^3 + 0 \times 2^2 + 0 \times 2^1 + 0 \times 2^0 = 8_{10}   \\
1110_2 = 1 \times 2^3 + 1 \times 2^2 + 1 \times 2^1 + 0 \times 2^0  = 14_{10} \\
$$
Similarly, we can convert the hexadecimal numbers into the decimal system. The following shows the conversion of some hexadecimal numbers into decimals.
$$
67_{16} =  6 \times 16^1 + 7 \times 16^0 = 103_{10} \\
8F_{16} =  8 \times 16^1 + 15 \times 16^0 = 143_{10}
$$

What is the place value F in 0xF5?

  1. 245
  2. 246
  3. 240
  4. 247

In this section, we saw that every number could have various representations. We can also represent other forms of information such as text, image, and sound into a binary representation. In the next section, we will look into how to do that.

Text, Image & Sound Representation in Binary

Consider the following scenario.

You went out on a solo adventure on a sailboat into the ocean. You have a wind-powered boat without an engine. At some point during your voyage, you enter into a windless patch of water, and the boat gets stuck. You get stuck for weeks, with nothing in view but water. At the same time, your navigation and communication devices run out of power. The only working equipment you have left is a signal lamp.
One day, you see a group of ships passing at some distance from your boat during the night. The question is, how do you ask for help?
How do you ask for help to the ships?

The clue of the signal lamp reveals out that it needs to be used to ask for help. You can use the signal lamp to ask for help. However, you can not simply randomly flash signals hoping that the ship will come to rescue you. Then how exactly to use a signal lamp to do that? The way you can ask for help is by signaling S.O.S. using your signal lamp.

S.O.S. is an internationally accepted distress signal used during emergencies.

Contrary to popular belief, S.O.S. doesn't stand for anything.  The phrases "Save our Souls" and "Save Our Ships " are, in fact, backronym rather than an acronym. When you flash distress signals, other boats will understand that you require help and will come to your aid, given that they can see it.

At this point, two questions might be unclear.

How can flashing a signal lamp in a fixed pattern mean S.O.S.?

How to flash a signal lamp so that it means S.O.S.?

Before we answer these two questions that let's take another scenario.

Suppose there is a multiple-choice based test. Each question has four options, from which the only one is correct. You and your friend decided to develop a communication strategy to cheat during the test.
Keeping in mind that I am in no way encouraging cheating off tests, how will you and your friend manage to exchange answers?

The obvious way is to use distinct gestures to symbolize different options. An example would be scratching your hair to represent option A or rubbing your eyes for option B, and so on. This method should help you communicate effectively without raising suspicions.

Let's take a moment to reflect. We just created something interesting here. What do you think we created when we used gestures to symbolize an answer?

We created a code that could only be understood between you and your friend. It is a secret language that you can speak with those who understand its meaning.

We can formally define code as a system of words, letters, signals, or symbols to transmit a message in secret form or a more convenient form.

The code you developed to exchange your friend's answers was to transmit a message in a secret form. One reason for coding is to enable communication in places where ordinary plain language, spoken or written, is difficult or impossible. Such as being stuck in a sailboat in the middle of a windless ocean. Flashing S.O.S. using a signal lamp, in the absence of other communication devices, is a convenient way to transmit requests for help.

When you convert information into symbols, the process is called encoding.

To encode a message, you must first define or use an existing standardized coding system.

While the reverse process of encoding is decoding.

What do you think is decoding?
Decoding is the process when you convert back the encoded symbols to retrieve the original message.

When your friend scratches his head, you can understand that he means the option A referring to your previously agreed code system.  There is no standardized system of cheating off in tests. Therefore, we usually create our system and assign them value.

We will use a widely used coding system called Morse code to communicate in the middle of the sea.

Morse Code

Morse code is a method used to encode characters as standardized sequences of two different signal duration.

These two signals are represented by dots (.) and dashes (_). The International Morse Code encodes the 26 English letters A-Z, some non-English letters, the Hindu-Arabic numerals, and a small punctuation set. There is no distinction between upper and lower case letters. We can take a look at the International Morse Code for 26 alphabets in table 4.

Table 4: International Morse Code
Alphabet Morse Code Alphabet Morse Code
A . _ N _ .
B _ . . . O _ _ _
C _ . _ . P . _ _ .
D _ . Q _ _ . _
E . R . _ .
F . . _ . S . . .
G _ _ . T _
H . . . . U . . _
I . . V . . . _
J . _ _ _ W . _ _
K _ . _ X _ . . _
L . _ . . Y _ . _ _
M _ _ Z _ _ . .

When you wish to send some messages using Morse Code, you will first have to convert your message in the Morse Code using the International Morse Code. Then you can send it through a communication channel or store it in a storage medium.

The receiver can decipher or decode the information contained by looking into the International Morse Code upon receiving the message.

What is the value of the following code written in morse code?$$\text{_ _ _ _ . _}$$

  1. O.K.
  2. C.Q.
  3. F.W.
  4. O.I.

Using the Morse code shown in table 4, we can encode alphabets in dots and dashes and send signals. We will use the signal lamp as a communication channel to transmit signals in our earlier case. Let's figure out how to use the signal lamp for communicating S.O.S.

In the International Morse Code, a dot is a single unit duration while a dash is three units duration. For using the signal lamp for communicating, we can assign the following:
$$
\text{Flashing for a single second } = dot  \\ \text{Flashing for three seconds } = dash \tag{3}
$$
Now we are ready to send a message across for help. In the International Morse Code shown in table 4, we can see that code for S is ... while for O is _ _ _. So, we can encode our message of S.O.S. in the following form.
$$
\text{SOS  } =\text{  . . .    _ _ _    . . .} \tag{4}
$$
Using our method of using the signal lamp as a communication channel, we can do the following:

  1. Flash for a second three times consecutively
  2. Flash for three seconds three times consecutively
  3. Flash for a second three times consecutively
  4. Repeat

If other ships receive your message, they will decode or interpret your message and come for help. You might notice that it takes around 15-20 seconds for someone to understand your message. You can fasten it up by proportionately reducing the signal lamp flashing duration.

Hopefully, now you have a little bit of an idea about code textual information in other representations such as gestures, signals, or even flashing.

Earlier, we primarily used Morse code in the telegraph. It's not used in computing anymore. However, you can say that Morse Code was an inspiration for text encoding in modern computing.

What does the Morse code using dots and dashes reminds you of with relation to the number system?

Representing text in Morse code using dots and dashes is similar to representing any number using only two numerals, i.e., $0$s and $1$s. Earlier, we saw that we could represent every number into binary representation while using only two numerals ($0$ and $1$).

Now that we understand how to code text in other representations, let's look into how we can encode text in a binary system for efficient communication.

Binary Representation of Text

To convert text into binary, we first require defining a mapping of the basic alphabets and characters. One of the examples of such mapping is the International Morse Code.

There are only two values a signal can take, dot and dash in a basic variation of Morse code. Therefore we can presume it to be similar to the binary number system.

The International Morse allows various combinations of dots and dashes to represent the alphabet of the English Language. Although the Morse Code is not binary in the strictest terms.

Can you guess as to what the word binary means?

The word binary means having two possible states like the binary numeral system. Each digit can be either 1 or 0. The states can also be defined as on & off or true & false.

A device that can be on the two possible states is called a single binary or two-state device.
Can you think of an example of a binary device?

An example of a binary device is an electronic switch that can either be on or off. Another example would be a light bulb, which can be turned on or off can act as a binary device. Earlier, we used a signal lamp to act as a binary device by assigning the two states.

A single binary digit or single on/off value is called a bit (Binary digit). A bit is also the basic unit of information or data.  Therefore, a single binary device is said to hold one bit of information.

Since a single bit can hold very little information, we often line many bits to store information. For convenience, a group of eight bits is called a byte. Each of these combinations can be assigned a symbol or information, just like the Morse Code.

If we take the value of light switch being on as $1$ and being off as $0$, the possible combinations or bit pattern of three switches is shown in table 5. We can store the symbols A-G using combinations of three light switches.

Table 5: Bit Patterns using three binary devices
Bit Pattern Decimal Number Assigned Meaning
0b000 0 Space
0b001 1 A
0b010 2 B
0b011 3 C
0b100 4 D
0b101 5 E
0b110 6 F
0b111 7 G

If you need to store all the alphabets in the English language and punctuation marks, we will require more bits. Being a binary number, they can also be represented in the form of their decimal counterpart.

Using table 5, let's implement a bit pattern that encodes a word.

Binary numbers are usually grouped into a set of four, separated by space. We can write the word BAD as 0b 0010 0001 0100.

Let's implement a binary code using a bunch of binary devices.

Figure 5: Representing BAD GABE using light switches

Figure 5 shows how the message BAD GABE can be represented using light switches. Anyone who has access to the character encoding shown in the the table above 5, will successfully decode the message. To include the space character in BAD GABE, we can include 0b0000 into the pattern. 0b000 means three switched off bulbs.

What text does the bit pattern 0b 0110 0100 1100 1010 represent according to table 5?

  1. $CAFE$
  2. $ACE$
  3. $GAFE$
  4. $FEDA$

Text Representation in Computers

Let's take a look at how text is represented in computers. When any key on a keyboard is pressed, a signal encoding a binary number is generated. According to a standardized character encoding, this signal is processed by the computer. It results in the typed character to appear on the screen.

Their several standardized character encoding, which encodes various characters or symbols to a binary number. Let's look at one called ASCII.

ASCII is a standardized code abbreviated from American Standard Code for Information Interchange. Before computers, telegraphs were mainly used for long-distance communication. Telegraphs used ASCII to encode information to send it over the wire.

The ASCII code takes each character on the keyboard and assigns it to a number. For instance, character A is assigned the number 65 or the binary number 0b 0100 0001. Table 6 shows the association of the symbols with numbers in ASCII.

Table 6: ASCII Symbols
Range of Numbers Assigned Symbols
33 - 47 Special Characters ( ! / + ...)
48 - 57 Numbers ( 0 - 9)
65 - 90 Uppercase Alphabets ( A - Z)
97 - 122 Lowercase Alphabets ( a - z)

ASCII code is a 7-bit character set. The highest binary number you can assign in ASCII is 0b 111 1111.

How many characters can be assigned to numbers using 7-bits?

You can only encode 27 or 128 unique symbols or characters using 7-bits. 128 symbols are quite less in comparison to our real-world needs.

If you wish to use the accents found in many European languages or a larger set of alphabets such as Cyrillic, Devanagari Script, or Mandarin, more bits are needed. A new set of standardized character encoding called Unicode was created to overcome ASCII's limitation. There are several sets of encoding available under Unicode. One of the popular Unicode character encodings is the UTF-8.

Unlike ASCII, UTF-8 uses several bytes. It can encode more than a million symbols, which is quite enough for all Earth's languages. Apart from text and characters from different languages, the UTF-8 also encodes emojis.

I hope you understood how the text elements are stored in the form of binary. Would you like to guess as to how images are stored in the form of binary? How do you think the computer stores images in binary and displays them onto the screen?

To understand how images are stored in binary, we need to look at what a digital image is. In the next section, we will see how computers display images.

Binary Representation of Images

A computer breaks an image into tiny elements called pixels to display it on a computer. A pixel (short for picture element) is a small square representing only one color. Lots of these pixels together can form a digital image.

Figure 6: Binary Image

The computer represents each pixel with a binary value to store an image. Depending on the number of bits in the binary value, we can choose to represent a different number of colors. For instance, figure 6 shows an image with two colors: black and white and uses a single bit to represent each pixel.

Therefore, every pixel in figure 6 is either 1 or 0.  Depending on whether the pixel has the value 1 or 0, it displayed as black or white, respectively.

When we represent an image using only two colors, it is called a binary image. Figure 6 shows that we can represent an image of F using pixels, which take only 1 bit and can either be black (1) or white (0).

Computer stores an image in the form of binary values spanning several lines. Each line is encoded from left to right and top to bottom. The image in figure 6 can be stored using the following binary values shown in figure 7.

Figure 7: Binary Values corresponding to rows of image pixels

For a computer to draw or interpret the image from the binary values, it needs more information other than the binary values. It requires numbers of pixels present in a row or width of the image and the number of columns or the height of the image. It also requires the number of bits used to represent each pixel. The number of bits used to represent each pixel is called color depth. The resolution of an image is a way of describing how tightly packed the pixels are.

The extra pieces of information such as color depth required for the computer to correctly display the image from binary numbers are called image metadata.

What do you think is the color depth, height, and width of the image in figure 7?

  1. 1-bit, 8 pixels height, 8 pixels width
  2. 2-bit, 16 pixels height, 16 pixels width
  3. 1-bit, 9 pixels height, 10 pixels width
  4. 2-bit, 9 pixels height, 10 pixels width

In the previous quiz, the color depth is 1-bit, as only 1-bit is used to represent each pixel while the image is 8 pixels high and 8 pixels wide.

An image that uses 4 colours requires at least 2-bits ( $2^2 = 4$ ) to represent each pixel.

2-bit Image
Figure 8: 2-bit image

Figure 8 shows a 2-bit image along with its binary values of image rows. In figure 8, the mapping of the colors for the corresponding bits is shown in table 7.

Table 7: 2-bit color map
Bit Pattern Color
00 White
01 Orange
10 Blue
11 Green

The mapping of bits to colours is called colour bitmap. The metadata for the above image in the figure 8 is as follows:

  • colour depth: 2-bit is used to represent each pixel
  • resolution: 6 pixels ( width ) x 7 pixels ( height ) = 42 pixels image resolution

On providing the binary values and the metadata, a computer will interpret the image and correctly render it.

A 2-bit color depth image can use only four colors. To represent images accurately, we require a higher color-depth.

If we use 16-bits to represent a single pixel, it can represent $2^{16}$ or 65,536. If we use 24-bits to represent a single pixel, it can represent $2^{24}$or 16,777,216 colors.

Can you guess the number of colors the average human eye can discern?

The average human eye can usually discern up to 10 million colors. Therefore, using 24-bit color depth is usually sufficient for most practical purposes.

Colour depth comparison
Figure 9: An image in different color depths

In figure 9, we can see the same image in various color-depths. Because pixels are very tiny in size, even with 1-bit color depth, the image detail is quite clear.

In this section, we briefly covered how computers convert images into binary. In the next section, we will look into how computers convert sounds into binary.

Binary Representation of Sound

To convert sound into binary, we must first capture it.

Which device do you think is used for capturing sound?

Capturing of sound is done using a microphone. A microphone is a type of transducer that converts the sound wave into an electrical signal. A transducer is a device that converts one form of energy to another.

Can you think of a device that converts electrical signals into sound?

A loud speaker is a transducer that converts an electrical signal into sound. Let's look into how a microphone converts sound into electrical signals.

A sound wave causes rapid air pressure variations, and a microphone is sensitive to these minor fluctuations in air pressure. A sensor is attached to the microphone whose electrical conductivity depends on the air pressure. When current passes through the sensor, the flow of electricity varies according to the air pressure variations. A device measures the fluctuating level of current called an Analog-to-digital converter (A.D.C.).

As sound waves are continuous, the A.D.C. takes precise measurements at a large number of times per second ( for instance, 44,000 times a second ) and creates a number representing the air-pressure at that time. The number of measurements or time samples per second is called the sampling rate. We measure the sampling-rate in kilo-Hertz ( kHz ). 1 Hz is one sample per second. Most CD-quality audio is sampled at 48 kHz or 48,000 samples per second.

We can then convert the collected samples into binary. They are recorded to the nearest whole number. If we plot the time samples, we will see that the sound wave now looks different because sampling does not consider what the sound wave is doing between each time sample. The sound loses quality as we are losing data between the time samples.

Figure 10 shows a graph of sample pressure variations and the corresponding sampling to digitally reconstruct the wave:

Sampling of Audio Signal
Figure 10: Sampling Audio Signals
How can we increase the quality of the reconstructred or stored sound?

In figure 10, we can see that based on how often the audio signal's measurement, the better is the reconstructed signal.

The higher the sampling rate, the more accurate its reconstructed wave is.

We can collect more detail about the sound this way. It does not lose as much quality when it’s converted to digital and back to analog again.

This is a brief overview of how sound is converted to binary. Do you want to guess as to how the binary values are played back?

The reverse process of recording sound is used to read the binary values and play the stored sound file.The stored binary values are read and transmitted to a something called Digital-to-Analog converter (D.A.C.).

First, a device reads stored binary values. A Digital-to-Analog converter generates a strong or weak current on a wire, depending on the number. A speaker can reconstruct the sound vibrations from the electrical audio signals. It is close to the original air vibrations during recording.

We can see the entire process of recording and playing the sound waves in figure 11.

Figure 11: Process of recording and playing sound

A point to note is that, when we measure the sound wave 48000 times a second, the storage space required quickly becomes huge. There are many compression techniques available that can shrink the size of the data without loss of information. These are called data compression techniques. This is a brief overview of how sound is stored in binary and played back on the computer. Let's do a short exercise.

Can you re-arrange the order of how sound is recorded and played back?

  1. Sound wave causes rapid air pressure variations
  2. Current passes through a microphone fluctuate according to the fluctuating air pressure
  3. A.D.C. takes precise samples of the fluctuating at a large number of times per second.
  4. The collected samples are stored in binary to the nearest whole number
  5. The stored binary values are read and passed to the D.A.C.
  6. The D.A.C. generates current on a wire depending on the number from the stored binary values.
  7. A speaker can generate sound from the fluctuating current.

So far, we have covered how sound, images, texts, and numbers can be converted into binary. At this point, you might be interested to know why binary or base-2 is used. Why not ternary (base-3) or decimal?

Guess of one good reason why we use binary instead of other bases?

Why binary is used in Computers

There are several advantages of using binary in computers. Here are four of the important reasons for using binary:

  1. Versatile Representation
  2. Binary devices are simple to build
  3. Signals in the form of binary are unambiguous
  4. We can create flawless copies of binary data.

Let's look into each of these reasons in a bit more detail.

Versatile Representation

The first advantage of using binary is we can use it to encode various types of information.

We have already seen earlier that numbers and text, image, and sound store in binary form. We can use patterns of bits to represent almost anything that follows some sort of pattern.

Binary representation is versatile enough to accommodate different types of data.

A more complex example would be videos in which images, along with the sound, can be stored in binary form. This ability to be able to represent almost anything is a major advantage of using binary.

Before moving on to the next advantage, let me ask you a question. A light switch is a device that has only two states on and off. A light dimmer is a device with multiple states and is used to control the brightness of the light. Which one do you think is easier to build - A light dimmer or a light switch?

Binary Devices

A light dimmer must gradually and smoothly change the current that reaches the light. It has more components than a light switch and must be carefully assembled. A light switch with two possibles states on and off is quite simple and easy to build compared to a light dimmer. The second advantage of using binary is - binary devices are easier to build.

This is also true for the tiny binary devices inside a silicon chip or magnetic storage, which powers modern computing. Switches with only two states are relatively easy to fabricate or produce. These binary devices are cheap, small, and reliable, and often billions of them can fit into a small area.

There are several ways to implement a bit pattern. Here are some ways we can implement bit patterns:

  • An electrical switch
  • Voltage on a wire.
  • A transistor
  • A small part of the light-reflecting surface, for example, C.D.s.
  • Part of a radio signal.
  • Part of an audio signal.

Earlier, we stored the message BAD GABE using twenty-four light-bulbs. Twenty-four light-bulbs can hold only 24 bits of information. A group of eight bits is called a byte.

Using light-bulbs to store information becomes expensive to keep a larger amount of information as they occupy a larger size. The hard-drives on a computer usually use which magnetic storage can hold more than 512 Gigabytes of data or 512 000 000 000 bytes or 512 billion bytes of information. That's a lot of storage.

Unambiguous Signals

There are three things you can do with information. You can store information, transmit information or process/transform information. The third advantage of using binary relates to information or signal transmission.

Before we move onto the advantage, what do you think does the word unambiguous mean?

The word unambiguous  essentially means not open to more than one interpretation.

The third advantage of using binary data is: Binary signal transmission is unambiguous and is immune to noise.

Let's take an example to understand this more.

Earlier, we suggested a hypothetical scenario where you and your friend decided to create a code to exchange answers during a multiple-choice questions based test. Suppose your friend suggested an unconventional method of transmitting code signals corresponding to the answer, shown in table 8.

Table 8: Unconventional Code Signals
Code Signals Answer
Motioning A using finger A
Motioning B using finger B
Motioning C using finger C
Motioning D using finger D

First of all, cheating off tests is not the right thing to do. Second, if you must cheat, then the above method is a recipe for disaster. It's unclear, it is prone to confusion, and most importantly, it's stupid.

Can you figure out what's exactly wrong with this method of communication?

When your friend is motioning, let's say the letter A, to get the full signal, you must observe the motion for the full duration. If you miss out on the part of the signal, you will most probably miss out on the entire information transmitted by the signal.

A better way is defining four different states corresponding to each answer, which are unambiguous and don't cause any confusion. For example,

Table 9: Conventional Code Signals
Code Signals Answer
Scratching hair A
Touching the forehead with the tip of a pen B
Touching nose with the tip of a pen C
Touching chin using the tip of a pen D

The signals mentioned in table 9 are a much effective way to communicate without any confusion. When your friend signals the answer A by scratching his hair, you can understand it even if you miss out on some portion of the movement.

Signals that continuously change values and can be anything in a range are called analog signals.

The sound waves we saw in the figure 10 are continuous signals. While signals that have a finite number of states are discrete signals. Discrete signals change only at discrete instants of time. Such signals are called discrete signals because they have a fixed number of definite states.

Binary signals are discrete signals.

The above two types of code signals differentiate between two types of signal - discrete and analog signals. Analog signals continuously vary with time. Their exact value at any particular instant is important for the receiver. This is similar to the code signal mentioned in table 8. Whereas in discrete signals, the receiver is interested in discrete states. As you might notice in the able two examples, discrete signals are unambiguous.

We can understand the noise immunity aspect of discrete signals using another example.

Noise Immunity
Earlier, I mentioned that the voltage on a wire could transmit a signal. Can guess how to use the voltage on a wire to transmit signals?

We can use the voltage on a wire to pass information in coded form. If you wish to send information to someone using a wire, you can encode a message into a fluctuating voltage. The receiver can record the voltage over some time and decode our message.

However, when you transmit the analog signals over a communication channel, it is most susceptible to external noises, which might cause a loss of information. The transmitted analog signal and the received signal often turn out to be quite different, as shown in figure 12.

Analog Signal
Figure 12: Analog Signal Transmission

Analog signals continuously change their value, and the information they carry is the exact value at any instant. The exact value of an analog signal at any time is essential. Therefore, analog signals are significantly affected during imperfect transmission.

To convert the analog signal into discrete binary signals, we need to ensure that at any instant of time, a signal represents one of two values. How do you think we can do that?

Using a threshold value, we can convert an analog signal into binary or digital signal. In such cases, a signal represents only one of the two discrete states at a discrete-time interval. Once we convert the analog signal into a digital signal, we can send information through it.

For instance, if the signal is above the threshold value, say 0.5, it can be considered 1 and if below, then 0. The essential advantage of using digital signals is that we longer need to worry about the signal's exact value. In figure 13, we can see this in action.

Digital Signal
Figure 13: Digital Signal Transmission

In figure 13, you can see that even though there is noise in the received signal, the reconstructed digital signal doesn't incur any information loss. The reconstructed digital signal is the same as the sent digital signal. This is why digital signals are said to possess considerable noise immunity.

Perfect Copies

The fourth advantage of using binary is a continuation of digital signal advantage.

Lets say you downloaded a file from the internet using a good internet connection. Do you think there is a loss of information when a file is downloaded from the internet to your computer?

There is no or minimal information loss when a file is downloaded from the internet. You might be so used to the fact that you take this for granted. The files you download from the internet are perfect replicas of the original files.

The fourth advantage of using binary is - we can make perfect copies using binary.

When we use binary signals for transmission, the receiver is only interested in the binary values. All it does is check if the signal is above or below the threshold. The receiver can do this quite perfectly unless the noise is not too great. For example, in figure 13, the original binary signal and the reconstructed binary signal are identical even though there is noise in the received signal. The original signal is recovered perfectly.

This process of recovering the original signal in digital signal transmission can be repeated as many times as needed with a flawless perfect copy made each time.

Bit patterns are often copied back and forth between processor & memory more than millions of times per second in computers. The copies of stored information need to be perfect each time. In this particular case, binary signals are highly useful for creating perfect copies.

Information stored in binary form does not change when we copy it from one medium to another. We can create an unlimited number of such copies. The ability to make perfect copies without loss in information is a compelling combination. The chances are that you are already accustomed to this that it may not seem significant. When you try to download a video or music file from the internet, the data has already been copied (downloaded) many dozens of times, using various transmission and storage methods. Yet, it doesn't affect your download, and you get a perfect replica of the data.

Video Streaming
Figure 14: Streaming video through various communication channels

Figure 14 shows a sample demonstration of how a simple download of the video passes through various storage and transmission methods.

I would like you to describe figure 14 briefly.

In figure 14, we see that actual information does not change from one medium to the next. Easier transmission and copying of data is a significant part of computers' advancement and the creation of multi-billion dollars worth of various technology companies such as Google, Facebook, Twitter, etc. This is a major part of the computer revolution, perhaps even more important than computers' actual computing.

In this section, we covered

  • representations that computers understand
  • representing text, image & sound in binary
  • why binary is used for computers

The next section will look into how computers process instructions and information represented in the binary.

Processing Instructions

Before moving on to understand how computers process information, let's look at the different parts of a computer system.

A computer system can be broadly classified into two of its components. Do you want to guess which are these two components I am referring to?

A computer system consists of two parts computer hardware and computer software. Let's start with the computer hardware.

Computer Hardware

A computer system is primarily composed of the following hardware components:

  • Processor
  • Input & Output Devices
  • Memory Devices
  • Main Memory
  • Secondary Memory or Storage

Processor

Let's start with the processor. What do you think does the processor do?

A computer is a machine that can automatically carry out a sequence of arithmetic or logical operations.

An example of an arithmetic operation is adding two numbers or subtracting two numbers.  While an instance of logical operation is to check if two different quantities are the same.

The processor does the primary task of carrying out the instructions. The rest of the computer systems' function is to provide the information or instructions that need to be processed and electrical power.

A processor has a small amount of memory that it uses to hold data and instructions for processing. A computer processor accepts binary data as input, processes it according to instructions stored in its memory, and returns the output in the form of binary data. A processor does the most critical work of the computer. Therefore, we often refer to a processor as the brain of the computers.

Input & Output Devices

Next are input and output devices. What do you think is the role of the input and output devices?

Input & Output devices help make the computer system interact with the outside world by moving data into and out of the system. Input & Output devices are commonly referred to as I/O devices.

Table 10: Examples of input & output devices
Input Devices Output Devices
Keyboard Monitor
Mouse Printer
Webcam Speaker
Networking Networking
In table 10, why do you think that networking is mentioned in both Input and Output Devices?

When you connect the computer to the internet or a local network, you can move data into the system and move it out of the system. Therefore, the network interface acts both as an input and output device.

The third computer hardware we will look into is memory. Why don't you guess what role the memory plays in the computer?

Memory

Computers use memory to store data.

There are two types of memory, Main Memory and Secondary Memory.

Both the memory stores data in the form of bit patterns. Although the way they implement bit patterns differs significantly. Let's start with main memory.

Main Memory

Main memory is as vital as the processor chip to a computer system. Fast computer systems have both a fast processor and a large, fast memory.

A processor chip only has enough memory to hold a few instructions of a program and data they need for processing. As a processor chip has comparatively less memory, complete programs, data and instructions required by the processor are stored in the main memory.

The main memory is intimately connected to the processor, therefore moving instructions and data into and out of the processor is pretty fast. The main memory consists of silicon chips, which has several million transistors that can act as binary devices. These transistors are used to store the bit pattern of incoming data and transmit it to the processor.

The main memory consists of a very long list of bytes. In modern computers, each byte has an address that is used to locate it. Figure 15 shows a small part of the main memory.

Figure 15: Memory address

Each box in this picture represents a single byte. Each byte has an address. In this picture, the addresses are the integers to the left of the boxes: 0, 1, 2, 3, 4, ..., and so on. Most computer memory addresses start at 0 and go up in sequence until each byte has an address. These memory cells can be accessed in any order or randomly, so the main memory is sometimes called Random Access Memory (RAM). When a computer is said to have 8 Gb of RAM, they usually talk about the main memory.

The data stored in the main memory can quickly and easily be changed. For the data to persist, it requires constant electricity. Such memory is also called volatile memory because the data stored evaporates as soon as your machine loses power.

If main memory loses all the data as soon as the machine loses power, how do you think computers can store data?

Anything you wish to keep for the long term is kept in secondary memory or storage. Let's next look at the secondary memory.

Storage

Secondary Memory or Storage is where data is stored for a long term basis. Examples of storage devices include hard disks, DVDs & portable hard disks. Unlike the main memory, the secondary memory doesn't require constant electricity to store the data.

Once you write some data onto the storage, it stays there even after the computer is turned off. The secondary memory, which is usually hard-disk inside a computer case, usually has larger storage than the main memory.

The reason for the persistence of data is the way bits are implemented in the secondary storage. For instance, a magnetic storage device has a large shiny, circular plate of magnetic material called a platter, divided into billions of tiny areas. Each area can be independently magnetized ( to store a 1) or demagnetized ( to store a 0). Therefore, the information stored in this magnetic disk persists even after switching the power off. All the disks and heads are sealed into a dust-free metal can.

Writing data to a hard disk is a slower operation compared to the main memory.

There are two types of memory in a computer due to the different needs they fulfill.

Table 11: Shows the difference between primary memory and Secondary memory
Primary Memory Secondary Memory
Read/Write operation are faster Read/Write operation are slower
Relatively more expensive Relatively less expensive
Lower Capacity Larger Capacity
Directly connected to the processor Not directly connected to the processor

Table 11 shows an important distinction between primary and secondary memory. In both the main and secondary memory, information and data are stored as patterns of bits.

Hard disks (and other secondary memory devices) are used for long-term storage of large blocks of information, such as programs and data sets. The data stored in the secondary memory is organized as files.

A file is a collection of information that has been given a name and is stored in secondary memory. The information can be a program or can be data.

There are different types of computer files, designed for different purposes. A file may be designed to store a picture, a written message, a video, a computer program, or a wide variety of other kinds of data. Some types of files can store several types of information at once.

The form of the information in a file is the same as with any digital information — it consists of bits, usually grouped into eight bits. A group of eight bits is called byte. Files are often quite large. Therefore their size is measured in usually measured in kilobytes (kb) or megabytes (Mb).

Data is stored in a computer in the form of bit patterns. How do you think a user interacts with the data stored on the computer?

We can interact with the files by using appropriate computer software, which we will look into in the next section.

Computer Software

A computer software is a collection of data and instructions that tell the computer's physical hardware how to work. A set of instructions is called a called computer program.

We can define computer software as a collection of data & instructions that tell the computer's hardware how to function.

As the processor processes all of the computer instructions, how do you think the instructions are represented?

The instructions are written in or compiled to a representation that the processor can understand, which is binary. Let's look into the different types of instructions in a computer.

There are two types of computer software.

Applications

Applications are a set of programs that is designed for users to use directly. Examples of such applications are Spreadsheet software, Word Processor, Web Browsers, and Computer Games.

System Programs

System Programs are a set of programs and software platforms which provide services to other software. The most important example of a system program is an operating system. Let's look at it in detail.

Operating System

An operating system or O.S. is a software program that enables the computer hardware to communicate and operate with the computer software. An operating system performs all the basic tasks like file management, memory management, handling input and output, and controlling other devices such as a keyboard, printers, and display.

An operating system is a vital part of any computer system. Can you name an operating system?

There are many operating systems available such as Linux, Windows, macOS, etc. Most computer systems can potentially run several OSs, such as Linux and Windows.

When a computer is started, the hardware first loads the operating system and keeps it running. Once the operating system runs, the user can begin interacting with applications and programs stored in the secondary storage.

The applications on a computer depend on the operating system to help them manage tasks. When you press a key on the keyboard ( hardware ), the operating system's job is to detect which key was pressed and provide the application's information. Upon receiving information from the O.S., the application responds to the user input.

The following is a high-level overview of what happens when a user interacts with an application.

  • The user clicks an application icon to start it.
  • The O.S. first determines the application name.
  • Then, it determines the related files on the secondary memory / hard disk where the application and its data are stored.
  • The O.S. finds an unused section of main memory that is large enough to hold the application data
  • The O.S. makes a copy of the application and its data in that portion of the memory
  • The O.S. arranges further resources for the application
  • Finally, the O.S. starts the application running.
  • As the application runs, O.S. manages background resources as well as providing input/output operations for the applications

We earlier mentioned that the main memory is directly connected to the processor. Keeping the contents in the main memory helps the processor execute the instructions written in the program faster.

Based on the above overview, can you rearrange the following operations in opening a web browser?

  1. The browser starts running.
  2. The OS finds an unused section large enough to hold the application related data and files of the browser.
  3. The OS finds the files related to the browser application in the storage.
  4. The OS copies the browser-related files onto the main memory.
  5. The user clicks on the browser icon to start the application
  6. The processor starts processing the instructions stored in the main memory

In this topic, we covered different components of a computer.  Let's understand how the processor executes the instruction in the next section.

The Processor Revisited

To understand how a processor executes the instruction stored in the main memory, we will need to revisit the processor. There are different types of processors available, but the three things are common in the processors. A processor has a control unit (CU), an arithmetic logic unit (ALU) and sets of registers. These components are shown in figure 16.

Figure 16: Components of a processor

Let's start with the control unit.

The Control Unit (C.U.)

The control unit contains digital circuitry that uses electrical signals to direct the computer system to carry out or execute stored program instructions. The control unit does not execute program instructions itself. It merely directs other parts of the system to do so.

The control unit must communicate with both the arithmetic/logic unit and memory.

The next component that we will look into is the Arithmetic Logic Unit (ALU). Why do you think the Arithmetic Logic Unit (ALU) is called so?

The Arithmetic & Logical Unit ( ALU )

An arithmetic logic unit (ALU) is a digital circuit used to perform arithmetic and logic operations.

Most of the processor operations are performed by one or more ALUs, which reads data from registers. The arithmetic/logic unit (ALU) contains the circuitry to perform various arithmetic operations such as addition, subtraction, multiplication, division, and logical operations. A logical operation is usually a comparison. ALU can check for six logical relationships: equal to, less than, greater than, less than or equal to, greater than or equal to, and not equal.

The arithmetic and logical operations may seem insignificant, but these operations are the building block of modern computing.

The ALU is heavily dependent on the registers for reading or storing data.

Can you think of an instance when you need to store data in an arithmetic calculations?

When you multiply two larger numbers, you often hold some information outside and access it later.

Multiplication of 34 and 8
Figure 17: Storing values during multiplication

Figure 17  shows how values are stored during multiplication. Similarly, the registers operate to hold information that is currently being processed.

Now, let's look at registers.

Registers

Registers are temporary storage areas for instructions or data. They are the smallest data holding elements that are built into the processor itself. However, they are not a part of the main memory. Instead, they are special storage locations that offer the advantage of speed.

Registers work under the control unit's direction to accept, hold, and transfer instructions or data and perform arithmetic or logical comparisons at high speed.

The fundamental difference between the register and memory is that the register holds the data that the CPU is currently processing. The memory contains program instruction and data that the program requires for execution.

Table 12: Different storage elements in a computer
Storage Elements Relative Access Speed Relative Capacity Relative Cost Permanent
Registers Fastest Lowest Highest No
Main Memory Fast Low/Moderate High No
Secondary Memory Slow Very High Low Yes

Earlier, we mentioned two other memory devices, main memory, and secondary memory. Table 12 illustrates how registers compare to the other memory.

Now that we covered a processor's components let's see how the processor interacts with the main memory.

How do you think the processor interacts with the main memory.

  1. A processor can read bit patterns from the main memory
  2. A processor can write bit patterns to the main memory
  3. Both 1 and 2
  4. None of the above

There are two ways in which the processor interacts with the main memory.

  • It can write a bit pattern to a byte at a given memory address, which results in the previous bit pattern in that location will be destroyed. The new bit pattern is now saved for future use.
  • It can read a bit pattern from a byte from a given memory address. The processor gets the bit pattern stored at that location. The contents of that location are NOT changed.
What kind of information do you think are stored in the form of bit patterns in the main memory?

The memory addresses in the main memory hold Instructions and data. The instructions are for the processor to execute while data are pieces of information required by the processor to execute the instruction.

Instructions

Given that you are aware that the computer executes arithmetic operations, can you think of a sample operation for a processor?

A sample arithmetic operation can be an addition or division of two numbers.

Let's take a simple arithmetic operation, say multiplication.

When you multiply two numbers, you usually write them in the following syntax:$$\text{Multiplication Operation : }a \times b$$ What is the symbol x called in the multiplication operation?

  1. Operand
  2. Operator
  3. Operazor
  4. Openheimer

In the previous exercise, the symbol $\times$ is called operator  while $a$ and $b$ are called operands.

Now that we identified operator and operand using an example, I would like you to define the terms operators and operands in your own words.

An operator is a symbol that represents a specific operation, whereas the operands are the inputs for operation.

Similarly, an instruction for a processor consists of operation code and operand.

Opcode (an abbreviation of operation code) is the portion of an instruction that specifies what operation is to be performed by the processor.
Operand usually specifies the data the operation is to be applied. The operands can represent a memory address of the value, register, or value itself.

Instructions are patterns of bits that correspond to different commands that a machine can carry out by physical design. Each type of processor is designed to understand and perform a specific group of instructions. The group of instructions is called the instruction set of the processor. Like the different languages that people understand, different processors have their own instruction set, which they can understand.

Examples of commonly used instructions that a processor are an addition, multiplication, subtraction, fetching values from memory, jumping, and moving bits.

Let's look at a generic instruction to understand how processors execute instructions. We will take an imaginary processor with the instruction set shown in Table 13.

Table 13: Sample instruction set for an imaginary processor
Instruction Set Opcode in binary Opcode in hex
Multiplication 0b10001011 0x8B
Addition 0b10001010 0x8A
Subtraction 0b10001001 0x89

We know that the instructions need to be in binary for the processor to read and understand. Instructions and data written in language consisting of binary numbers that a processor can read and interpret is called machine language, a language that the machine understands.

The first few characters of machine language instructions usually represent the opcode(s), while the rest represents the operands. Let's say we want to execute the following instruction.

Multiply the values in the memory address 0b1001000 and 0b111111 and store the result in 0b1001110. The opcode for multiplication being 0b10001011.

We can represent the instruction in machine language in the following form.
$$
\text{Sample Instruction : }\overbrace{\text{10001011}}^{\text{opcode}} \underbrace{\text{ 1001000 111111 1001110}}_{\text{operands}}
$$
The sample instruction's initial part represents the opcode for multiplication, while the operands represents the main memory addresses. The sample instruction is written in machine language or binary. Although we cannot make sense of it, it is something our imaginary processor will be able to perform.

Machine Language written in pure binary seems to take a lot of space for so little instruction. Can you think of a more compact representation of the instructions for the processor other than binary?

Earlier, we also read about the hexadecimal system. It turns out that Machine language can also be expressed in hex-format (hexadecimal) - the number system with base 16.

The binary system and hex are very interrelated with each other. It is easy to convert from binary to hex and restore from hex to binary. We can rewrite the above sample instruction in hex in the following way.
$$
\text{Sample Instruction in hex : }\overbrace{\text{8b}}^{\text{opcode}} \underbrace{\text{ 48 3f 4e}}_{\text{operands}}
$$
The instructions look more compact now but still unreadable for humans. To understand the machine language instruction, we will need to refer to the instruction set of our imaginary processor.

This is a tedious process.

In the early days of computing, all the instructions were hand-coded in machine language. Can you think of some disadvantages of coding directly in the machine language?

Machine Language instructions proved to be quite challenging for humans.

One obvious disadvantage was the need to memorize the several opcodes of the processor's instruction set.

The second was the need to carefully write the exact memory addresses as it is prone to mistakes.

Researchers developed a new language to make it easier to work with machine language, called assembly language. The assembly language replaced the numerical operation codes with Mnemonics codes that was much easier to remember and allowing symbolic address names instead of a numerical memory address.

To understand mnemonic codes, let's create some mnemonic codes for our imaginary processor in the table 14.

Table 14: Mnemonic Assembly Opcodes
Operation Numerical Opcode Assembly Opcode
Addition 8a ADD
Multiplication 8b MUL
Subtraction 8c SUB

Table 14 shows the assembly mnemonic opcodes corresponding to each numerical opcode. Mnemonic codes make it easier for humans to write instructions for a processor without memorizing the numerical opcodes. Whenever you need to use the opcode for subtraction, you can write SUB instead of writing the numerical opcode 8c.

We should note that the choice of the memory address in the above code is arbitrary. Any address that is not already filled can be used for storing or reading values.

Programmers using assembly language don't have to worry about the actual memory address because each data address is referred to by a name, called symbolic names.  You can store the memory address as a symbol or strings of character and then use it instead of writing the full memory address each time you require it. For instance, say we assign the memory address 0x48 with the symbolic address name length. Whenever we wish to refer to the address 0x48, we can use the address length instead.

Earlier I mentioned that the processor could only process machine language which binary or hexadecimal. How do you think the processor can execute the instructions written in assembly language?

The short answer is that the processor doesn't need to deal with the assembly language directly.Before the assembly language instruction is ready to be processed, it is first converted to the corresponding machine language using assembler.

There are several assembly language variations, each designed to work with a particular processor. We will rewrite our machine language instruction into an imaginary assembly language designed to work with our processor.

We can rewrite the above instruction again in an imaginary assembly code by storing the three memory addresses in the symbolic address names length, height, and area.
$$
\text{Sample Instruction in Assembly : }\overbrace{\text{MUL}}^{\text{opcode}} \text{    } \text{ } \underbrace{\text{  length   height   area}}_{\text{operands}}
$$
Now, the instruction is a bit clear. We can read the instruction as follows:

Multiply the values stored in length and height memory address and store the result in memory address area.

The main memory holds both instructions and data required for the execution of the instruction. Let's store the instruction at an arbitrary memory address, 12f. We will also store operands value in the addresses referenced by symbolic address length as 7 (0x7) and height as 20 (0x14). Table 15 shows how our main memory might look before executing the instruction.

Table 15: Memory addresses before executing instruction
Address Address in Decimal Symbolic Address Name Value
0x12f 303 0x8b 48 3f 4e
0x48 72 length 0x7
0x3f 63 height 0x14
0x4e 78 area 8c

Which of the following is true for the main memory shown in the table 15?

  1. The memory address 0x12f holds the instruction
  2. The memory address 0x48 holds the value of the operand length.
  3. The memory address 0x3f holds the value of the operand height.
  4. All of the above is true.

Let's look at how a processor might execute this generic instruction stored in the memory.

Using the assembly language suddenly made our, seemingly gibberish, instruction readable. Now let's look into how our imaginary processor performs our sample instruction.

The Instruction Cycle

Earlier, we mentioned that when a program is executed, the operating system copies the main memory instructions. The processor executes a single instruction in the following three phases.

Fetch - Decode - Execute

Let's start with the first phase - Fetch.

Fetch

In the fetch step, the control unit requests that the main memory provide it with the instruction stored at a memory address indicated by the control unit's program counter. The process of fetching data is shown in figure 18.

Step 1
Figure 18: Control unit fetching instruction from main memory

A program counter, also called the instruction pointer, is a register that indicates where the computer is in its instruction sequence. It holds either the memory address of the instruction currently being executed or the address of the next instruction to be performed.

What do you think the control unit does after receiving the instruction from the main memory?

Decode

Once the instruction is retrieved from the memory address, the instruction is stored in the instruction register. Then the control unit decodes the instruction in the instruction register.

Instruction registers are registers that hold the instruction being executed by the processor. Figure 19 demonstrates the decoding step.

Figure 19: Control unit decoding fetched instruction

The control unit decodes the instruction in the instruction register into operands and opcodes and generates the ALU's necessary signal to execute the instruction. In our cases, it decodes that this is a multiplication operation that needs to happen. If any of the operands are memory addresses, the values in the memory address are fetched and stored in a register.

What do you think the ALU does after receiving the signal from the control unit?

Execute & Store

The arithmetic/logic unit then executes the instruction decoded by the control unit. The ALU performs the actual operation on the operand as per the operation code or opcode. This phase of execution is referred to as the Execute phase.

The control unit tells the ALU what operation to perform on that data. The ALU stores the result in an output register. This is shown in figure 20.

Step 3- Execute
Figure 20: ALU executing instruction

For our sample instruction, ALU performs the multiplication.

The ALU's result from the multiplication is stored in the memory address specified by symbolic memory address area.  The control unit moves the data between these registers, the ALU, and memory.

Repeat

The program counter register is automatically incremented for each instruction cycle to retrieve instructions sequentially from memory normally. The previous steps are again repeated for the next instruction provided by the program counter. The Fetch-Decode-Execute cycle is called one instruction cycle. It is one of the basic operations that a computer performs.

That's a brief overview of how the processor executes a single instruction. The processor executing a simple instruction might seem a little bit underwhelming. And most of the instruction sets are, in fact, consist of simple operations.

Then how does the computer can possess such versatile capabilities, you might think. That maybe has to do with the number of instructions a computer performs in a second.

Do you want to guess as to how many instructions does a processor performs in a second?

A modern processor executes over millions of instructions in a second. The speed of a processor is often measured in Millions of instructions per second (MIPS). A modern processor can do perform 100 thousand MIPS or 100 billion instructions per second.

Executable Program

A machine instruction consists of several bytes in the main memory. A collection of machine instructions in the main memory is called an executable program or machine language program.  The processor executes the corresponding operation for the machine instruction one at a time, but can perform billions of them in a second.

All the little operations based on the instructions adds up to something useful, such as playing a video or browsing the internet.

This also means that do something useful with the computer, we have to provide a huge number of machine instruction. Although assembly language is easier to work with than machine language, it is still tedious to work with assembly language.

In the next section, we will try to understand how we usually write a set of instructions or computer programs that a computer can execute without dealing with machine language.

Summary

In this section, we covered how computers execute the instruction provided in machine language. In the next section, we will understand how we usually set instructions or computer programs that a computer can execute without dealing with machine language.

Writing Computer Programs

A computer program is a set of instructions to perform specific tasks. In computers, these sets of instructions are simply referred to as a program.

When a computer executes or performs a program, it follows its instructions in a predefined manner. It is very much similar to the act of cooking by following a recipe. Although the recipe has to be specifically well defined otherwise, the program will not be executed or will execute incorrectly in the case of computers.

You might question what a well-defined recipe or instruction means and answer that let's take the recipe for making an egg omelet shown in figure 21.

Figure 21: Recipe for Egg Omelette

Depending on how well you understand the recipe and execute the instructions, you might still end up with completely different results than intended. This happens because instructions in figure 21 are still pretty ambiguous, which leaves room for confusion.

For example, when the recipe says "Beat the eggs, salt & water in a bowl" it doesn't specify the exact procedure to beat the eggs or the order in which we should follow the instruction.

Or how to "Heat the pan until hot".

Why do you think the instructions are ambiguous?

In our day-to-day communications, the intentional meaning behind the words is usually inferred from multiple competing meanings.

Every sentence is written concerning a given context. The meaning of the sentence is derived from the context in which it has been presented.

When we write instructions for the computer to perform a specific task, we need to ensure no room for ambiguity. We need to specify every detail of how to perform a task. It turns out that such a level of specificity is quite difficult to achieve in English or any other natural languages such as French, German, or Hindi. To instruct the computer to perform a specific task, we require a specific type of language designed to be unambiguous.

Such languages are called formal language. Examples of formal languages include notations used to describe mathematical axioms, proofs, and equations.

The formal language in which we write a set of instructions for the computer to perform a specific task is called programming language.

We have already encountered two programming languages in the earlier sections. Can you take a guess the programming languages I am referring to?

Machine Language and Assembly Language are both programming languages used to write instructions for the computer.

Before covering formal languages in detail, let's look at some of a language's basic characteristics.

The following are the general characteristics of a language.

  • The building blocks for any written language are symbols. In English, the alphabets, numbers, and punctuation constitute the symbols of the language.
  • When a series of symbols are strung together, they form another element of a written language called word. Only finite combinations of symbols are accepted as a valid word.
  • Each valid word has an underlying meaning.
  • A set of words can be combined in an accepted manner to form a sentence to express a statement, question, or command.
  • Based on a set of rules, a sentence might mean something or might be complete gibberish.

These are the basics of a language.

A language is characterized by mainly two sets of rules relating to syntax and semantics.

  • Syntax: Rules that tell which symbols are allowed to be used and how to put them together to form valid expression.
  • Semantics: Rules that tell you the meanings of valid expressions & symbols.
Before understanding these rules in detail, can you take a guess what syntax means?
In general, syntax refers to the arrangement of words and phrases to create well-formed sentences in a language.

We can define syntax as rules that tell which symbols are allowed to be used and how to put them together to form valid expression. Syntactic rules let us know the validity of a word or a sentence.

Can you now take a guess what semantics mean?

The word semantic relates to meaning in a language. The rules of semantics tell you the meanings of valid expressions & symbols.

The group of valid symbols used in a language is often referred to as tokens. The rules about the order in which these tokens can be combined is called structure. Syntactic rules govern the structure of sentences or expressions, including the order of the valid symbols and group of such symbols.

Therefore, rules relating to the syntaxs relates to the form of the language. In contrast, semantic rules deals with the underlying meaning.

In natural languages, the syntactic rules are flexible and lenient. Because they are flexible, they have space for creating new words and phrases such as:

  • Sup? which is short for What's up ?
  • Peace out, bruh !, which is erm ...... I have little idea what this means but this is a valid expression in the English Language in some parts of the world.
What can you say about the syntactic and semantic rules of formal languages as opposed to natural languages?

For formal languages, the syntactic and semantic rules are precise and strict. For instance, mathematical statements in formal notation are considered correct only when they use the proper mathematical notation (syntax). The resulting statement is meaningful (semantic).

Now, let's look at formal languages.

Formal Languages

The rules are flexible and lenient for natural language because the rules that govern natural languages are not human-made but evolve naturally over a long period. In contrast, formal languages are created artificially.

For formal languages, the syntactic and semantic rules are precise and strict.

Consider the following statement expressed in the formal language of mathematics:
$$
1 + 4 = 5 \tag{A}
$$
In statement A, tokens present in the expression are +, =, 1, 4, and 5. These are valid symbols in mathematics, and the order in which these tokens are arranged also forms a valid expression. Therefore, it is syntactically a valid mathematical expression.

The statement states that adding one to four results in five, which is correct. Therefore semantically, this statement is also valid.

Consider the following statement expressed in the formal language of mathematics:
$$
1 + 4 = 5 \tag{A}
$$

Here, tokens present in the expression are $+, =, 1, 4$, and $5$. These are valid symbols in mathematics, and the order in which these tokens are arranged also forms a valid expression. Therefore, syntactically, it is a valid mathematical expression.

Is the statement A semantically correct? Why or why not?

The statement A states that adding one to four results in five, which is correct. Therefore semantically, this statement is also valid.

Let's take another mathematical statement.
$$
1+4=7 \tag{B}
$$

Is the statement B syntactically correct? Why or Why not?

Similar to statement A above, statement B also has valid tokens and correct structure. Therefore, statement B is syntactically correct.

Is the statement B semantically correct? Why or why not?

The statement B expresses that adding one to four results in seven, which, as we know, is incorrect. Therefore, statement B is syntactically correct, although semantically incorrect.

Let's take another statement.
$$
\text{+ 1  3} = 4 \tag{C}
$$

Is the statement C syntactically correct? Why or why not?

Although statement C has valid tokens, they are arranged in a wrong order, making it an invalid or syntactically incorrect expression.

Is the statement C semantically correct? Why or why not?

In formal languages, syntactically incorrect statements often make it difficult to understand the underlying meaning. Therefore, we cannot comment if the statement C is semantically correct.

Let's take a statement in the English Language.
$$
\text{Th1s $tatement has c0rrect $tructure but 1nvalid t0ken$.} \tag{D}
$$

Is the statement D syntactically correct? Why or why not?

Statement D shows a statement in the English language with invalid tokens, but a correct structure makes it syntactically incorrect.

What about the meaning of Statement D? Is the statement D semantically correct? Why or why not?

Although the sentence is syntactically incorrect, the sentence is still valid semantically because we can understand it's an underlying meaning.

This also shows how lenient natural languages are concerning their rules relating to semantics.

Now let's examine the expressiveness of natural and formal languages.

Take the following mathematical statement.
$$
x = \sqrt{(y + 2)^3} \tag{E}
$$
Statement E shows a mathematical expression involving two unknown variables $x$ and $y$. If you were to read the expression in the English language, it would be something similar to statement F.
$$
\text{The unknown variable } x  \text{ equals to the  square root of the sum} \\ \text{ of the unknown variable } y \text{ and 2, raised to the power 3.} \tag{F}
$$

The two statements E & F expresses the same meaning in a formal and natural language.

Can you comment on the expressiveness of formal languages compared to natural language?

If you compare statement F with statement E, you can see that the formal language of mathematics expresses the same thing in a more concise manner.

It is easier to read and understand statement E than reading statement F, given that you are familiar with the underlying rules.

Formal languages are more concise in expressing meaning than natural languages.

Natural languages are full of words and sentences whose meanings depend on the context. Words might have a different meaning for different situations. Natural language employs more words to provide context to reduce the ambiguity, which makes expressing in the language more verbose with many redundant parts.

Natural Languages also contain symbolism, idioms, metaphors,  and allegory, which makes the underlying meaning of the expression well-hidden unless someone understands the actual meaning.
$$
\text{Luffy keeps trying to get it working,
but I think he's beating a dead horse.} \tag{G}
$$
Statement G says something about beating a dead horse which is an idiom meaning to waste effort on something when there is no chance of succeeding. Someone unfamiliar with the idiom might take the statement at its face value and think Luffy is literally beating a dead horse.

In contrast to natural languages, statements and expressions in formal languages are unambiguous and have a well-defined meaning. Because the formal language is straightforward, the expressions are less verbose and concise. Also, a statement in formal languages precisely means what it expresses.

Table 16: Difference between Natural Language & Formal Language
Natural Language Formal Language
Ambiguous Unambiguous
More redundant and verbose Less Redundant and concise
Obfuscate the actual meaning by employing symbolism Precisely means what it expresses
Evolves naturally Artificially created for a specific domain
Rule related to syntax and semantics are flexible Rules pertaining to syntax and semantics are precise
Examples - English, Hindi, French, and Japanese. Examples - Chemical Equations, Programming Languages, and Mathematical formulae.

The differences between Natural & Formal Languages are summarised in Table 16. In the next section, we will dive into more about the semantics of expressions in a formal language.

Semantics

As we stated before, the semantics of a language relates to the meaning of symbols, tokens, and expressions. Consider the recipe of an omelet shown in figure 21. To follow the recipe, we must understand what each instruction means.

I mentioned it earlier that the recipe is not well-defined. This is because the recipe instructions hide many details, which is believed to be commonly understood by everyone.

For example, the instruction relating to heating the pan assumes that everyone knows how to heat a pan and what a pan is. This simplified instruction comprises a bunch of other hidden instructions to make it generalized.

This process of simplifying instructions or communication of leaving out all concrete details and extracting the essential features is called abstraction.

Abstractions help in hiding away a lot of underlying inferred meaning. Effective communication about things in the abstract requires an intuitive or shared experience between the communicator and the communication recipient.

Abstraction in daily life
Figure 22: Communication is simplified using abstractions.

Let's take figure 22 as an example, in which a person is instructing his friend to bring him a glass of water. The section in the figure 22 without abstractions (or more accurately using lesser abstractions) expands on the instruction to highly specific steps.

At this point, can you describe what abstraction means in your words from whatever you have understood so far?

Abstraction hides away many details of communications. If we start adding more details and specificity to the sentence, we will realize that we can do this for a very long time. Let's expand upon the original statement by adding more details to it.

Abstraction Pyramid

When we expand upon each word, we get an abstraction pyramid. The further we go down in the pyramid, the more we have to unpack the words' specific meaning. This can go on forever in natural languages, as humans communicate in shared abstractions, which cannot be explicitly detailed.

For example, take the conversation shown in figure 22. We can expand upon the original statement by adding more details to it as shown in the figure 23.

Abstraction Tree
Figure 23: Expanding on the abstractions to show the underlying abstraction pyramid

For formal languages, especially programming languages, it is a higher-level thinking tool, possibly an end to the abstraction pyramid.

Before learning more about the abstractions in programming languages, let me ask you a question. What forms the foundation for instructions written using programming languages?

Semantics in Programming Language

Machine language is the only language that a processor then executes directly without a previous transformation. Also, each instruction is written in machine language often corresponds to a specific instruction for a processor to execute. So, it is safe to say that machine languages form the basis on which higher abstractions can be formed.

Programming languages are used to instruct the computer to perform specific tasks or computations.

Being a formal language, the instructions for performing the tasks are completely detailed, and rules for deriving their meaning are precise. When you write a program using a programming language, the computer first reads those instructions and performs them. Performing an instruction of a program is called the execution of the instruction. Every instruction of the program should be properly detailed for the computer to execute it.

For example, let's say we want to write a program that accepts two numbers, multiplies them, and prints the result. Before we can instruct the computer to do that, the definition of numbers in terms of bit patterns in memory, how to take inputs from the keyboard, how to multiply two numbers, and how to print the result on the screen must be understood or known by the computer.

However, if every single time we need to multiply two numbers, we were to define what numbers are and what multiplication means, that would be a bit of drudgery. Software development in programming languages employs many tactics that hide away a lot of implementation details so that we can focus on solving problems at hand.

An example would be the one we encountered in the earlier section. We converted an instruction in machine language to our imaginary assembly language. We did this by storing the three memory addresses in the symbolic address names length, height, and area and using the mnemonic opcode M.U.L..

$$
\text{Sample Instruction in hex : }\overbrace{\text{8b}}^{\text{opcode}} \underbrace{\text{ 48 3f 4e}}_{\text{operands}}
$$

$$
\text{Sample Instruction in Assembly : }\overbrace{\text{MUL}}^{\text{opcode}} \text{    } \text{ } \underbrace{\text{  length   height   area}}_{\text{operands}}
$$

The amount of implementation details a language takes to care for us determines how easy or difficult it is to program in that language. Even though assembly languages provide a very little abstraction over the machine language, it is still much easier to work with than machine language. This is pretty similar to the process of abstraction we saw in figure 23.

Based on the levels of abstraction that the languages employ, the programming languages are divided into high-level languages and low-level languages.

Guess as to what low-level languages mean?

Low-level Programming Languages

The low-level programming languages provide little or no abstraction from a computer's instruction set. The commands or functions in the language map closely to processor instructions.

The term low-level indicates the low abstraction between the language and instruction set understood by the computer, which is why low-level languages are sometimes also described as being close to the hardware.

What are some low-level languages that we have already covered?

We are already familiar with the low-level programming languages: Machine Language and Assembly language.

We earlier mentioned that each processor has a somewhat different instruction set based on its internal architecture. This is often referred to as instruction set architecture (ISA) or computer architecture or simply architecture.

An instruction set architecture is an abstract model of a computer. A realization of an I.S.A., such as a central processing unit (CPU), is called an implementation. Instructions in machine languages directly correspond to the specific instruction set architecture.

The machine language program maps closely to the instruction set of a particular processor of a family of processors. Because assembly depends on the machine code instructions, every assembler has its assembly language designed for precisely one specific computer architecture.

A program is said to be portable if the same code works in different environments - for example, different processors or different operating systems. Programs written in low-level languages tend to relatively non-portable due to being optimized for a certain type of processor's architecture. Furthermore, it requires memorizing or looking up numerical opcodes or mnemonic codes for every instruction and is difficult to modify.

Programmers rarely write programs directly in machine code because it requires attention to numerous details that a high-level language handles automatically.

Examples of High-level languages are Python, C, C++, Java, and Lisp.

I earlier mentioned that the low-level languages have low abstraction. In contrast to low-level languages, high-level languages have higher or stronger abstractions. What do you think a high level of abstraction means?

High-level Programming Languages

The high-level programming languages lets you express instructions without worrying about the implementation details. When you drive the car, you only need to work with a couple of things, such as brakes, accelerators, and gears. You don't worry about how every tire or the underlying engine works.

The underlying working of the car is the implementation detail. That's an example of working with higher-level abstraction.

High-level abstraction can also be understood by taking the example of getting a taxi or cab in a city. Can you rearrange the order of things that were needed to be done to get a taxi?

  1. Ask the taxi driver if they can take you to your destination.
  2. Go outside near the street and wait for an unreserved taxi to show up.
  3. If they answer in the affirmative, get inside the taxi.
  4. If the answer is negative, wait for another taxi and repeat all the above steps.
  5. Show your hands up to signal the taxi to stop.

The previous exercise is a high-level overview of how to get a taxi. Now, contrast this with the cab sharing app called Uber. One of the earliest pitch by the founders of Uber was this:

You push few buttons, and a black car shows up at your doorstep.
Where did the implementation details go?

The implementation details are taken care of by the Uber App. The app user can deal with scheduling cabs and choosing a destination without performing any previous steps to get a taxi.

It's worth noting that the user interacts with a taxi's abstraction, not a physical taxi itself. In a way, the Uber App is a higher abstraction on the top of the activity of getting a taxi.

Can you think of another example that provides an abstraction on the top of physical activity?

E-commerce companies such as Amazon provide an option to shop around on their website and add them to a virtual cart. Contrast this with going into a mall and doing the shopping while dragging around a physical cart. It's only fitting to say that E-commerce, such as Amazon, provides an abstraction on shopping while hiding the implementation details.

Similarly, higher-level languages take care of the implementation details and provide you a framework to work towards problem-solving rather than dealing with the implementation details.

Let's revisit the earlier sample instruction where we wrote the instructions for multiplying two numbers in our imaginary machine language.

Which of the following is true for a programmer writing a sample instruction for multiplying two numbers in our imaginary machine language?

  1. The programmer needs to look up the opcode or mnemonic code for multiplication.
  2. The programmer needs to convert the input into binary or hexadecimal representation
  3. The programmer needs to store the converted input's value in two unused memory addresses
  4. All of the above.

The implementation details for the multiplication of two numbers are too many in a machine language. Let's contrast to how something similar is done in the higher-level languages.

We can perform the same calculation in Python in the following manner.

>>> 7 * 20
140

This is it. It will be helpful if you notice the following.

  1. No need to look up memory addresses to store value.
  2. No need to change the representation of the numbers to binary or hexadecimal.
  3. No need to look up the correct opcode for the operation.
  4. And much more readable.

You can certainly see how convenient it is to work with a higher-level. In contrast to low-level programming languages, higher-level may use natural language elements, be easier to use, or may automate (or even hide entirely) significant areas of computing systems (such as. memory management), making the process of developing a program simpler and more understandable than when using a lower-level language.

The amount of abstraction provided defines how "high-level" a programming language is. Rather than dealing with registers, memory addresses and call stacks, high-level languages deal with names, lists, objects, complex arithmetic or Boolean expressions, functions, loops, and other abstract computer science concepts, with a focus on usability over optimal program efficiency.

We will look into all these concepts subsequently in later chapters. For now, the only thing you need to know is high-level programming languages make it easier to write instructions for computers, which coincidentally are easy to read and maintain.

For instance, the following is a sample program written in the high-level language Python.

for num in range(51):
    
    # Divisible by both 3 & 5
    if num % 3 == 0 and num % 5 == 0:
        print("fizzbuzz")
        continue
    
    # Divisible by only 3
    elif num % 3 == 0:
        print("fizz")
        continue
    
    # Divisible by only 5
    elif num % 5 == 0:
        print("buzz")
        continue
    else:
    	print(num)
Listing 1: FizzBuzz program written in Python

At this point, you don't need to know what this program does. However, you can notice that the program is very much readable.

I mentioned earlier that the processor could only process instructions in machine language. How do you think the processor understands the instruction written in the above form?

When instructions are written for a computer in a language other than machine code, it is called source code. The source code needs to be converted to a representation that the processor can execute.

Based on how the source code is converted, programming languages are classified into compiled and interpreted.

Compiled Languages

Let's look into compiled languages first.

Often, high-level languages generate an executable program entirely by compilation.

Compilation is a process of converting the source code into machine language.

To understand how compilation works, let's take a program written in C programming. The program takes user input and prints if the number is odd or even.

#include <stdio.h>
int main() {
    
    int num;
    printf("Enter an integer: ");
	
    // Read the User's input
    scanf("%d", &num);

    // True if num is perfectly divisible by 2
    if(num % 2 == 0)
        printf("The number %d is even.", num);
    else
        printf("The number %d is odd.", num);
    
    return 0;
}
Listing 2: Odd and Even in c, OddEven.c

The above source code is stored in a text editor with a filename OddEven.c.  The source code first needs to be converted into an executable program containing machine language instruction before the processor can execute it. This is done using a C compiler program for C programming language. This is figure shown in figure 24.

Compiler
Figure 24: Compiling a c program

The C compiler converts the source into an executable file that can be executed directly by the processor. It takes the source code file as input and produces a machine language program as output. Figure 25 shows how the program is executed.

Executable Program
Figure 25: Execution of compiled program

As we mentioned earlier, a machine language program is called an executable program, or sometimes, just executable. In the above case, the executable program is called OddEven.exe and can be saved on the hard disk. The processor copies the program's executable version into the main memory to run the program and executes the instructions.

The entire source code is compiled to a corresponding executable file. How does the programmer modify the compiled program?

For compiled languages such as C, the programmer needs to modify the source code written in the OddEven.c file and re-compile to generate the corresponding executable file to modified source code.

Interpreted Languages

In an interpreted language, the source code is converted into another representation, not necessarily machine language. The program is executed with the help of an interpreter program.

Before going into details, let me ask you a question. What's the difference between an interpreter and a translator?

Usually, translators accept a document, for instance, written in Swahili, and they translate the whole document into another language, say English. The compilation is similar to the end-to-end translation of a document.

While interpreters, who are people, interpret what the person is saying at that particular instance in real-time.

Figure 26 is an example of such interpreter interpretation between two roommates.

Figure 26: With and without an interpreter

In interpreted languages, such as Python, the source code is interpreted to something else, which in Python is called bytecode representation.

Let's rewrite the same program written above in Python .

try:
    num = int(input('Enter an integer : '))
    if num % 2 == 0:
        print("The number {} is even.", num)
    else :
        print("The number {} is odd", num)
else:
    print("Please enter an integer")
Listing 3: Odd and even in Python, OddEven.py

A python interpreter is required to run the program. Therefore, to execute the OddEven.py file, we would need a Python interpreter. This is done using the following command:

python OddEven.py

The python interpreter reads the instructions one by one and executes them.

Interpreter Program
Figure 27: Execution of a Python program using Python interpreter

Figure 27 shows how the python interpreter executes source code written in Python.

If a programmer wishes to modify a python program, how does he do that?

The programmer can modify the source code in OddEven.py and re-run the program using an interpreter. There is no extra step of compiling, unlike compiled languages. This is a crucial difference between interpreted and compiled language.

This brings us to the end of our chapter on fundamentals of computing.

If I were to ask you now to define python programming language in your own words, how will you define it?

Python is a high-level, interpreted programming language.

And starting the next chapter, we will start our journey into learning Python.