Programming Languages: Understanding the Basics from User Interface to Hardware

Share:

You’ve created an amazing interactive dashboard using your favourite Python scripts. You press a button, and a beautiful chart shows company revenue trends. Exciting stuff, right?

But hold on a second. Have you ever wondered what happens behind the scenes when you tap that button on the screen? Let’s take a quick peek. 

In this article, we’ll discuss how humans interact with computers, explore high and low-level programming languages, make some comparisons, and tie it all together with the journey from GUI to hardware.

You have so many friends and you talk to them in English or Hindi or German. Your computer is also your friend – always ready to listen to your commands. However, it doesn’t understand the same language that you use to chat with your other buddies. To have a real conversation with your computer friend, you’ve got to speak its language only. 

And that is called programming language and why they came in the first place

You must learn and speak fluently in a programming language if you want to interact with your new friend. 

High-Level & Low-Level Programming Language

Now, the challenge is that a computer understands only 0 and 1, called binary numbers. That means the programming language should be a massive set of 0 & 1 to communicate your message to the computer. Right? Well, in that case, it will be really difficult for you to convert everything in 0/1 because we humans are not used to speaking in binary terms.

Hence, to save you, we have two levels of programming languages: High & Low.

1. What is a high-level programming language?

High-level programming languages have a lot of similarities with human languages. It is a human-friendly language and comes with a lot of simple instructions. They look more like the words and sentences we use every day. For example, to print something we use an English-like instruction “printf” (print formatted). 

There are several high-level languages like C, C++, C#, Java, and Python. These languages make it much easier for us to write programs and tell the computer what to do. 

2. What is a low-level programming language then?

Low-level programming languages are machine-friendly languages and closer to the computer’s actual language of 0 & 1. 

They talk to a computer’s central processing unit (CPU) and help to execute the original instructions. There are primarily two types of low-level programming languages: assembly language and machine language.

2a. What is a Machine Language then?

Machine language is the lowest level of programming language. It consists of binary code, a sequence of 0 and 1, that directly represents your instructions that a computer’s central processing unit (CPU) can execute. 

Machine language is difficult to write and understand due to its binary nature. After all, you cannot think and work in a binary system – right? Further, as it is closer to the CPU, Machine language is CPU-dependent. It is specific to a particular computer architecture and not portable which means the same code may not be executed in another machine with a different CPU configuration.

2b. Well, what is Assembly Language?

Assembly language, another low-level language, is just a step above machine language. It has a bit more human readability. 

It uses mnemonic codes (short, human-readable abbreviations) to represent machine instructions and memory locations. Examples are ADD, SUB (subtract), and JMP (jump).

These mnemonics are then translated into machine code using an assembler. Assembly language provides a way for programmers to work with low-level instructions while still using symbolic names for operations and memory locations, making it more understandable compared to machine language.

The diagram below summarises the overall architecture.

Please note that both machine language and assembly language are low-level languages and they interact directly with the computer’s hardware, giving programmers control over the CPU’s operations and memory. And, both are dependent on the hardware architecture of the host machines and are not very portable.

Why not learn low-level languages instead of high-level programming languages?

Well, that’s a great question! 

While low-level language is close to computer hardware, it is super-fast. 

However, as you move farther from human abstraction towards machine hardware, coding becomes more complex and difficult to imagine. It gets really tedious as the program size and complexity increase. 

Just think about telling someone how to make a sandwich by explaining each atom that makes up the ingredients – way too detailed!  

An example is shown below to just give an overview.

An Example of Low-Level Conversion

Let’s take a simple Python code where we want to add `5 + 3` and see how it would be represented in assembly language and machine language. Keep in mind that low-level language syntax can vary slightly depending on the assembler you’re using, but I’ll provide a general example.

Python
				
					result = 5 + 3
				
			
Assembly Language (x86 Intel Syntax)
				
					section .data
    result db 0; Declare a variable to store the result

section .text
    global _start

_start:
    mov al, 5; Move the value 5 into the AL register
    add al, 3; Add the value 3 to the AL register
    mov [result], al; Store the result in the 'result' variable

    ; Exit the program
    mov eax, 1
    mov ebx, 0
    int 0x80

				
			
Machine Language (x86 Intel Syntax)
				
					Binary representation (hexadecimal):
B0 05 04 03 A2 00 00 00 B3 01 B0 01 BB 00 00 00 CD 80

Explanation:
B0 05       ; Load the value 5 into AL register
04 03       ; Add the value 3 to AL register
A2 00 00 00 ; Store AL in the 'result' variable
B3 01       ; Load the value 1 into BL register
B0 01       ; Load the value 1 into AL register
BB 00 00 00 ; Load the value 0 into EBX register
CD 80       ; Execute the system call (exit)

				
			

As you can see, the assembly and machine code is much more detailed and closer to how the computer’s hardware works compared to the high-level Python code.

That’s why data scientists and analysts, use higher-level programming languages to code. They are much easier and more intuitive to code – though you may compromise a bit on execution speed!

So, who does the high to low-level conversion?

Well, this happens in a few steps:

You write your instructions or code in a high-level language like Python or Java. 

Next comes two translator tools that convert the high-level to Assembly language:

1. Compiler: A compiler takes your entire high-level code and translates it all at once into low-level code. This low-level code can be directly understood and executed by the computer’s hardware. 

Once the compilation is complete, you have a separate file containing the translated code that can be executed anytime. 

In summary, it translates the entire high-level code into low-level code before execution, creating a separate file that can be run multiple times.

2. Interpreter: An interpreter reads your high-level code line by line and translates it into low-level code on the spot. Each line of your code is translated and executed immediately, without the need to create a separate translated version. 

This means that the computer can understand and execute your code without the extra step of creating a separate translated file.  

In summary, it translates and executes high-level code line by line, without creating a separate translated file, enabling real-time execution.

Please note that, both compilers and interpreters have their own advantages and use cases. Compilers can optimize code for better performance since they have a broader view of the entire program, while interpreters provide quick feedback and allow for interactive debugging as you see immediate results of each line of code.

Can a high-level language have both compilers and interpreters?

Programming languages can have either compilers, interpreters, or even both! The choice between using a compiler, an interpreter, or both depends on various factors, including the language’s design, its intended use cases, and the preferences of its creators and users. Some examples:

Languages with Compilers:

  • C, C++, Ada, Rust: These languages often have compilers. The source code is translated into machine code by the compiler, creating a standalone executable file that can be run directly.

Languages with Interpreters:

  • Python, Ruby, JavaScript: These languages are often associated with interpreters. The source code is read line by line and executed immediately without the need for a separate compilation step.

Languages with Both:

  • Java: Java code is first compiled into an intermediate form called bytecode using a compiler. Then, a Java Virtual Machine (JVM) interprets the bytecode at runtime. This is a mix of compilation and interpretation.
  • C#: Similar to Java, C# code is compiled into Common Intermediate Language (CIL) code, which is then executed by the .NET runtime. Again, this involves both compilation and interpretation.

It’s important to note that some languages can have multiple implementations that use different strategies. For instance, Python has both interpreters (like CPython) and compilers (like Cython or Nuitka). These alternative implementations offer different performance characteristics or features.

Additionally, modern techniques are blurring the lines between compilation and interpretation. Just-in-Time (JIT) compilation, used by languages like Java and C#, compiles code at runtime, combining some benefits of both approaches.

So, in the magical realm of programming languages, there’s quite a variety of ways that high-level code can be turned into something the computer can understand and execute, ranging from pure compilation to pure interpretation and everything in between!

Comparing Programming Languages: Speed & Performance

Imagine you have a group of messengers, each with their own strengths and weaknesses. These messengers represent different programming languages, and their delivery speed is analogous to the language’s performance.

C and C++ Messengers: Swift and Direct
C and C++ messengers are like runners who take the shortest path to their destination. They are quick and efficient because they communicate directly with the computer’s hardware. These messengers can deliver messages incredibly fast because they translate the message into a format the computer understands without any extra steps. This direct communication boosts their performance.

Java Messenger: Fast with a Helper
The Java messenger is like a swift runner, but with a helper who translates the message to the local language before delivery. Java uses a “Just-in-Time” (JIT) compiler, which translates the message into a format the computer understands just before delivering it. This adds a little overhead due to the translation, but once the translation is done, the runner’s speed is comparable to C and C++ messengers.

C# Messenger: Agile Translator
The C# messenger works similarly to the Java messenger. It’s quick and agile, with a translator who helps convey the message to the destination. The .NET runtime translates the message into a format the computer understands just before delivery. This adds a small delay, but once the translation is complete, the messenger’s speed is competitive.

Python Messenger: Expressive and Thoughtful
The Python messenger is like a thoughtful and expressive storyteller. They focus on delivering the message in a way that’s easy for everyone to understand. However, they might take a bit longer to prepare the message, and they don’t run as fast as the swift runners. Python’s code goes through interpretation or is executed by a virtual machine, which introduces some delay compared to languages like C or C++.

Factors Influencing Performance:
1. Abstraction: Languages like Python offer more abstraction and expressiveness, which might impact speed.
2. Compilation: Directly compiled languages (C, C++) can be faster since they generate machine code.
3. Interpretation: Languages with interpretation (Python, Java, C#) introduce a layer that affects speed.
4. Optimization: Advanced compilers and JIT techniques can improve speed.
5. Hardware Advances: Faster processors and smarter compilers benefit all languages.

In summary, the choice of programming language depends on your project’s requirements. If speed is crucial and you’re comfortable with more technical details, C and C++ might be great. For a balance of speed and productivity, Java and C# can be strong contenders. Python offers ease of use and readability at the cost of some performance.

Comparing Programming Languages: Speed & Performance

LanguageCompiler/InterpreterSpeedCommon ApplicationsEase of UseCompanies
CCompilerFastSystem software, embedded systems, game enginesModerateMicrosoft, Apple, Google
C++CompilerFastGames, applications, systems programmingModerateAdobe, Facebook, Microsoft
JavaBoth (JIT)ModerateWeb applications, Android appsModerateGoogle, Amazon, Netflix
PythonInterpreterModerateWeb development, data analysis, scriptingEasyInstagram, Spotify, Dropbox
JavaScriptInterpreterModerateWeb development (front-end), interactive websitesEasyFacebook, Google, Microsoft
RubyInterpreterSlowerWeb applications, scriptingEasyTwitter, Airbnb, Shopify
SwiftCompilerFastiOS/macOS app developmentEasyApple
C#Both (JIT)ModerateWindows applications, game developmentModerateMicrosoft, Unity, Electronic Arts
PHPInterpreterModerateWeb development (server-side), dynamic websitesEasyFacebook, WordPress, Wikipedia
KotlinCompilerFastAndroid app development, web applicationsEasyJetBrains, Trello, Uber
Go (Golang)CompilerFastWeb services, backend development, networkingModerateGoogle, Dropbox, Docker

Please note that this list is not exhaustive and focuses on providing a snapshot of some notable companies associated with each programming language.

Finally, what happens when you click a button on GUI?

Here is what happens step by step.

1. Graphical User Interface (GUI)
The journey just begins at the graphical user interface, where users interact with the application through visual elements like buttons, menus, and text fields. For example, you click a ‘run’ button using Python’s Tkinter framework.

2. User Interaction
Users engage with the GUI, clicking buttons, typing text, or making selections. These actions generate events that the application responds to. For example, The Tkinter framework registers your mouse click on the button and identifies the button you clicked.

3. Application Logic
The application’s code, written in a high-level programming language, processes these events and determines the appropriate responses. It orchestrates the behavior of the GUI.

4. Operating System Interaction
The application communicates with the operating system to request resources such as memory and processing time. The operating system manages these resources among various applications.

5. Hardware Abstraction and Device Drivers
Specialized software components known as device drivers provide an abstraction layer for hardware components. They allow the application to interact with hardware without needing to understand hardware intricacies.

6. Translation to Assembly or Machine Code
The high-level code is translated into a lower-level representation: assembly or machine code. This is the language that the computer’s central processing unit (CPU) can directly understand and execute.

7. Hardware Execution of Machine Code
The CPU executes the translated assembly or machine code. It fetches instructions from memory, performs arithmetic operations, and manipulates data according to the program’s logic.

8. Direct Hardware Interaction (Optional)
In some cases, applications need to interact directly with hardware components such as motors, sensors, or lights. Specialized hardware drivers facilitate these interactions.

9. Data Processing and Presentation
The CPU processes data as instructed by the machine code. It performs tasks such as rendering graphics, calculating results, and managing memory.

10. GUI Update and Hardware Output
The results of the CPU’s processing are reflected in the GUI. Visuals are updated, charts are redrawn, and data is presented in response to the user’s actions.

11. User Feedback
Users observe the effects of their interactions as the GUI responds to their actions, providing real-time feedback on the application’s state.

12. Event Handling and Interaction Loop
The application’s code continuously captures events, manages GUI updates, and orchestrates the interaction loop between user actions, software logic, and hardware execution.

A really long long process. Hope this gives an idea how much it takes to just run a simple code that you have just written!

Final Thoughts

In this tutorial, we have discussed what is a programming language, high and low-level programming languages, compilers, interpreters, assembly and machine language, and some comparisons around programming languages.

We just have covered the basics and actually, it is a whole branch of study that you can take on later.

We have added a few questions/quiz asked frequently in interviews. Try to check your understanding here.

NEWSLETTER

Get all the latest posts delivered straight to your inbox.

You have been successfully Subscribed! Ops! Something went wrong, please try again.

About Us

We are a dedicated team of industry practitioners, academic researchers, and data enthusiasts committed to sharing knowledge, ideas, and insights to empower individuals on their data-driven journey.

Contact Info

contact@datascienzz.com

© 2023 DataScienzz. Powered by DataScienzz

Scroll to Top