A programming language is a way for a human to tell a computing machine what to do and how to do it. Just like different languages are spoken in different countries and cultures, similarly, different programming languages evolved for different computing needs, programmers’ needs, users’ needs, and for different environments in which the program runs.
Different programming languages have different use-cases and all the above reasons have led to the evolution of many programming languages that are present now, just like how different sports exist today for different reasons. Learning programming is like learning sports. You can learn a sport at a very high level like the rules of the game, various players and roles, etc. However, at the same time, you can learn the sport in quite a large detail, building various techniques, practicing them, and building accuracy in a specific role.
Broadly speaking, in computer science too there are high-level programming languages and low-level programming languages. A high-level programming language is a coding language where the instructions have a strong level (high-level) of abstraction from the details of the computer. It is like developing or coding a remote that can work for any television. It uses natural language elements, easier syntax, easier rules, automates or even completely abstracts the programmer from memory management, making the process of writing a program simpler and easier. This high level of abstraction is why these programming languages are called “high-level programming languages”. On the other hand, low-level programming languages are very machine-specific and work with specific hardware only. It is like developing or coding a remote that can work with only a specific television, but it really works quickly and efficiently compared to the remote that works for all televisions.
When we’re teaching coding to kids, we’re largely sticking to high-level programming languages in order to start from high-level of abstraction, and then as the kids grow and develop themselves, they can move down to low-level programming languages, if needed.
Broad definition of hierarchy of programming languages:
- Source code: Instructions that are coded by a developer
- Compiler: An application that converts the above source code into assembly, bytecode or machine code on the specific machine that the code is run on.
- Assembly: A low-level source-code like language specific to a machine or an application.
- Bytecode: A low-level binary representation of code that can be run by other applications.
- Machine code: A binary representation of code that can run directly by machine hardware.
A low-level programming language is a code that provides little or no abstraction from a computer’s instruction set architecture—commands or functions in the language map closely to processor instructions. Generally, low-level programming language refers to either machine code or assembly language. The word ‘low’ refers to the low or non-existent amount of abstraction between the language and machine language; therefore, programs written in low-level languages tend to be mostly non-portable.
Machine code is the only code that a computer can directly process without any transformation. Most programmers today don’t write code in machine language as it is tedious to write code in machine code. But often coders get a glimpse of machine code while they’re debugging core dumps in high-level programming languages like C++ or Java.
Hexadecimal representation of 32-bit x86 machine code. Don’t get into the details of this, this is just to indicate what does machine code looks like.
8B542408 83FA0077 06B80000 0000C383 FA027706 B8010000 00C353BB 01000000 B9010000 008D0419 83FA0376 078BD989 C14AEBF1 5BC3
One level above the machine code is the assembly code. In the below code, the hardware registers and memory of the x86-64 processor are directly named and worked within the below code. Don’t get into the details of this code too, but the point to be noted is the memory registers of the hardware are directly named in the code which is never done in a high-level language.
_fib: movl $1, %eax xorl %ebx, %ebx .fib_loop: cmpl $1, %edi jbe .fib_done movl %eax, %ecx addl %ebx, %eax movl %ecx, %ebx subl $1, %edi jmp .fib_loop .fib_done: ret
Examples of Low-level programming languages:
C is a high-level language by syntax but because you manipulate memory with pointers and because you can write in-line assembly code within the high-level language syntax, C can be also considered as a low-level language. ALGOL too is a low-level language.
As we saw above, machine-level language and assembly-level language are low-level languages too. Machine Language consists of machine technicalities such as binary opcodes, addresses, and registers that you put into successive memory locations that can be directly executed without any further processing. One may think it doesn’t get any lower than machine language, but there is at least one lower level of code called the microcode. The microcode executes the machine language. On the other hand, Assembly language is a level above machine language that lets you use short abbreviations for the opcodes, registers, and addresses. The assembler just does a little bit of simple translation and outputs machine language instructions.
Examples of High-level programming languages:
Code written in high-level languages comes closer to English logic-based thinking in syntax as shown below. Sample high-level code is written in Python for a simple calculator of two numbers.
Hope this is useful, thank you.