JavaRush /Java Blog /Random EN /Levels of programming languages
Marat Sadykov
Level 41

Levels of programming languages

Published in the Random EN group

Introduction

What are the different programming languages? What kind of concepts are embedded in them? How did they develop? In this article, we will look at the types of programming languages ​​based on the so-called levels - from machine codes (low level, close to computer hardware) to languages ​​such as Java or C# (high level). The fewer transformations the text listing of the program undergoes along the way of turning into a set of zeros and ones, the lower the level.
Levels of programming languages ​​- 1
Next we will look at:
  1. Low-level languages ​​(machine codes and assembly)
  2. Intermediate level (C, Fortran….)
  3. High level (C++, Java, Python, Ruby, JavaScript...)
The level also characterizes how much detail the listing of the future program needs to be detailed to implement the implementation. How simple is this process for humans? The level of a language should not be considered an unambiguous indicator of its capabilities. A programming language is a tool that is effective in one area and less useful in others. Both the joiner and the carpenter work with wood. The first has a main tool - a set of chisels, the second - an ax. However, a carpenter will make a carved cabinet more elegant, and a carpenter will build a house faster. Although each is capable of doing the other's work, they will do it much less efficiently. Various data in a computer are represented as sets of zeros and ones. Control commands for its processing are the same data containing instructions that determine the location of the necessary information and the method of modification.

Machine languages ​​(Lowest level)

We will have to make a short visit from the Software area to the Hardware area. Let's look at it in a simplified form. The processor is the main “brain” of the computer. The motherboard on which it is installed contains controllers that are used to interact with other devices via buses (data channels for communication).
Levels of programming languages ​​- 2
Some work at high speed (red arrows): the processor draws commands from memory and manipulates data, the video card, especially in 3D games, consumes huge amounts of textures, shapes, pixel coordinates and other objects to build an image on the monitor screen. Others (due to limitations in the speed of information exchange) do not need such high indicators. Various internal and external devices are connected in the diagram with green arrows.

The inner world of the processor

All processor commands come from memory for execution in binary form. The format, number, subset of instructions depend on its architecture. Most of them are incompatible with each other and follow different ideologies. And also the type of command strongly depends on the mode (8/16/32... bit depth) and the data source (memory, register, stack...) with which the processor works. The same action can be represented by different instructions. The processor has instructions for adding two operands (ADD X,Y) and adding one to the specified one (INC X). Adding a triple to an operand can be done as ADD X,3 or by calling INC X three times. And, for different processors, it is impossible to predict which of these methods will be optimal in terms of speed or memory footprint. For convenience, binary information is written in hexadecimal form. Let's consider part of a familiar program (C language, the syntax of which is similar to Java)

int func() {
    int i = getData("7") ;
    return ++i;
   ...
}
Code that implements the same actions in the form of a sequence of instructions for the processor: ... 48 83 ec 08 bf bc 05 20 00 31 c0 e8 e8 fe ff ff 48 83 c4 08 83 c0 01 ... This is what the low-level programming language for the Intel processor actually looks like. A fragment that calls a method with an argument and returns the result incremented by one. This is machine language (code), which is transferred directly, without transformations, to the processor for execution. Pros:
  • We are completely masters of the situation, we have the widest possibilities for using the processor and computer hardware.
  • All options for organizing and optimizing code are available to us.
Minuses:
  • It is necessary to have extensive knowledge of the functioning of processors and take into account a large number of hardware factors when executing code.
  • Creating programs that are slightly more complex than the example given leads to a sharp increase in the time spent writing code and debugging it.
  • Platform dependence: a program created for one processor will generally not function on others. It is possible that for this processor, in other modes of its operation, code editing will be required.
Machine codes were widely used at the dawn of computers; there were no other methods of programming in the era of computer pioneers. Currently, they are occasionally used by microelectronics engineers when developing or low-level testing of processors.

Assembly language (low level)

Unlike a computer, you and I perceive information better in text/semantic form rather than in digital form. You can easily name fifty contact names on your smartphone, but you are unlikely to be able to write their corresponding phone numbers by heart. It's the same with programming. We move up the type ladder by taking three basic steps:
  • Let us associate one symbolic instruction to groups of digital processor instructions that perform corresponding actions.
  • Let's highlight the arguments of the processor instructions separately.
  • Let's introduce the ability to name memory areas, variables, and the location of individual commands.
Let's compare fragments of the previous program in machine code (center) and in assembly language (right):

2004b0     48 83 ec 08      sub    $0x8,%rsp
2004b4     bf bc 05 20 00   mov    $0x2005bc,%edi
2004b9     31 c0            xor    %eax,%eax
2004bb     e8 e8 fe ff ff   callq  getData
2004c0     48 83 c4 08      add    $0x8,%rsp
2004c4     83 c0 01         add    $0x1,%eax
As you can see, the process of writing a program has been simplified: there is no need to use reference books for generating digital command values, calculating transition lengths, distributing data in memory across its cells, and other processor features. We describe the required action from a set of symbolic commands and the arguments necessary for the logic of execution, and then the translator program translates the text file into a set of zeros and ones understandable to the processor. Pros:
  • The process of writing and modifying code has been simplified.
  • Control over all hardware resources was maintained.
  • It is relatively easier to port the program to other platforms, but they require modification depending on hardware compatibility.
Minuses:
  • Assembly language is a low-level programming language. Creating even small sections of code is difficult. In addition, it is also necessary to take into account the specific operation of the equipment.
  • Platform dependence.
The most popular Java demo example:

public static void main(String[] args) {
    System.out.println("Hello World!");
}
will look (NASM syntax, using Windows API and kernel32.lib) as follows:


        global _main
	extern  _GetStdHandle@4
	extern  _WriteFile@20
	extern  _ExitProcess@4
 
	section .text
_main:
	; DWORD  bytes;	
	mov 	ebp, esp
	sub 	esp, 4
 
	; hStdOut = GetstdHandle( STD_OUTPUT_HANDLE)
	push	-11
	call	_GetStdHandle@4
	mov 	ebx, eax	
 
	; WriteFile( hstdOut, message, length(message), &bytes, 0);
    push	0
	lea 	eax, [ebp-4]
	push	eax
	push	(message_end - message)
	push	message
	push	ebx
	call	_WriteFile@20
 
	; ExitProcess(0)
	push	0
	call	_ExitProcess@4
 
	; never here
	hlt
message:
	db  	'Hello, World', 10
message_end:
Like machine codes, assembly language is more often used by engineers and systems programmers. It is used to write hardware-dependent parts of the operating system kernel that are time-critical or critical to the implementation features of drivers for various peripheral devices. But lately they have been resorting to it less and less, since its use greatly reduces the portability of programs to other platforms. Sometimes they use the disassembly process - they create an assembly listing of a program from digital codes to parse the logic of executing small fragments. In rare cases, if the original high-level code is not available: analysis of viruses to combat them or loss of source code. Assembly language is considered to be the first/second generation (we will not consider separately pseudocodes before the emergence of assembler and their difference from symbolic commands). I would like to highlight the use of assembler in Demo Scene: a fusion of art, mathematics and low-level coding, embodying the artistic ideas of their creators in the form of programs that generate video clips with resource limitations. Often the total size of the program and data file should not exceed 256 bytes (4/64 kilobyte format is also popular). Here is an example of a 4 KB program:

Group C/Fortran languages ​​(intermediate/high level)

With the development of the capabilities of computer technology, the amount of functionality and timing of implementation of code in assembler were no longer satisfactory. The costs of writing, testing and maintaining programs grew an order of magnitude faster than their capabilities. It was necessary to reduce the requirements from the programmer in terms of knowledge of the functioning of the equipment, to give him a tool that would allow him to write in languages ​​close to human logic. Move to a new level of programming language types. Provide the ability to split into various modules with further sequential calling (procedural programming paradigm), provide various types of data with the ability to construct them, etc. Additionally, these measures brought improved portability of the code to other platforms, more comfortable organization of team work. One of the first languages ​​that supported all of the above was Fortran, developed in the 50s of the last century . The ability to create in text form with a description of the execution logic using loops, branches, subroutines and operating with arrays and presenting data in the form of real, integer and complex numbers delighted engineers and scientists. In a short time, scientific “frameworks” and libraries were created. All this was a consequence of the fact that Fortran is still relevant today, albeit in a narrow scientific environment, and is developing, since the baggage of developments is very large, the IMSL library alone has been actively developing since 1970 (!), how many similar relevant software can you remember? -old-timers? Another branch of development of languages ​​at this level is C. If Fortran became a tool for scientists, then C was created to help programmers creating application software: operating systems, drivers, etc. The language allows you to manually control memory allocation and gives direct access to hardware resources. C programmers have to control low-level entities, so many are of the opinion that C is an advanced assembly language and is often called a “mid-level” language. Having introduced data typing into assembler, elements of procedural and modular programming, the C language is still one of the main languages ​​for system programming, which is also facilitated by the rapid development of microelectronics in recent times. All kinds of gadgets, controllers, network and other devices need drivers, implementation of protocols for collaboration and other relatively low-level software to implement interaction with the equipment. All of the above contributes to the demand for the language today. Object-oriented and functional principles were further developed in the form of C++, C#, Java, taking a lot from the C syntax. Pros:
  • Simplification of the code creation process: introduction of types, division into modules, reduction of program listings.
  • Transparent logic of the underlying algorithm due to the move away from machine codes to more human-readable commands in a semantically descriptive style.
  • Portability. It became enough to recompile the program text for execution on another platform (possibly with a slight modification).
  • Speed ​​of compiled programs.
Minuses:
  • Lack of automatic memory management and the need for constant monitoring.
  • Lack of implementation of object-oriented and functional programming concepts.

Development of high-level languages

High-level programming languages, in terms of software creation, have increasingly begun to move away from machine codes and implement various programming paradigms in addition to procedural ones. These also include the implementation of object-oriented principles. C++, Java, Python, JavaScript, Ruby... - the range of languages ​​of this type is the most popular and in demand today. They provide more opportunities for implementing a variety of software and it is impossible to clearly determine the “specialization” of each of them. But the popularity of application in relevant areas is due to libraries/frameworks for working with them, for example: JavaScript - Frontend. The language was designed for interaction between a client web browser and a user and a remote server. The most popular libraries are Angular, React and VUE. Currently, it is relatively actively used on web and other servers (backend), Node.js is especially popular. Ruby - Backend. It is used to create scripts (service files) and on web servers. The main framework is Ruby On Rails. Python is a scientific and engineering domain (besides the web domain). It is an alternative to standard computing and mathematical packages (Mathematica, Octave, MatLab...), but has the usual semantics of the language and a large number of libraries. Has many fans in the field of machine learning systems, statistics and artificial intelligence. Frequently used libraries include django, numpy, pandas, and tensorflow. C++ – Universal, evolutionary development of the C language. Provides functional and object-oriented programming capabilities without losing the ability to interact with low-level hardware. Due to this, productivity and flexibility are realized when creating software, but the price also corresponds: a high barrier to entry due to the complex specification of the language, the need for independent control over resources when executing the program. Many single-user and system software are written using it: operating system modules (Windows, Symbian...), games, editors (Adobe Photoshop, Autodesk Maya...), databases (MSSQL, Oracle...), players (WinAmp...), etc. It should be noted that modern software is a complex product, the development of which uses several programming languages ​​at once, and it can be very difficult to determine the degree of participation of each of them in the overall result.

Further progress

Recently, another type of programming has been gaining popularity - functional (further development of the language level) . Here is another type of abstraction for calculations - functions that take a set of functions as arguments and return another one. The role of variables is played by the same functions (variables that are familiar to us are simply constant expressions, similar to final before a type declaration in Java). The function itself is closed in its scope, the result of its operation depends only on the arguments passed. Two remarkable properties follow from this:
  • For testing, we only need function arguments (the result of the work does not depend on external variables, etc.).
  • A functional-style program is miraculously concurrency-ready: sequential function calls can be issued in neighboring threads (since they are not affected by external factors) and do not require locks (that is, there are no synchronization problems). A good incentive to devote time to this topic, given the widespread adoption of multi-core processors.
However, the entry threshold is higher than for OOP: for effective code it is necessary to build a program, describing the execution algorithm in the form of functions. But also for a pure functional style it would be nice to know the basics of logic and category theory. The most popular are Haskell, Scala, F#. But do not be afraid, elements of functional programming have appeared in Java (as well as in other modern third-generation languages) and they can be combined with OOP. You will get to know all these details in more detail at the JavaRush online internship. The field of logic programming (the next level of languages) has not yet found wide practical application due to its low demand. Building programs requires knowledge of the fundamentals of discrete mathematics, predicate logic, constraint tools and other branches of mathematical logic. The most popular active language is Prolog.

Conclusion

Currently, the most common languages ​​are OOP. Java, since its inception, has always been in the top, usually in the top three, popular languages. In addition to OOP, it contains elements of functional programming, and you can combine different styles of writing your programs. The range of applications of Java is very wide - these are business tasks, the implementation of web servers (backend), the main language for creating Android applications, cross-platform programming environments and workplaces (IDE/AWM) and modeling, and much more. Java's position is especially strong in the Enterprise sector - an area of ​​corporate software that requires high-quality and long-lived code and the implementation of the most complex business logic.
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION