The beginning of programming languages
As history has progressed, computers’ computation power has become stronger and stronger. Thus, programming languages were born, becoming more readable but less efficient over time. However, what is the origin of these numerous languages? That is what we will explore today.
Nowadays, programming languages are of a single flavor; however, assembly languages have multiple flavors. That’s because Assembly languages (often abbreviated as ASM, hence the file format) are the ancestors of all modern programming languages. Compared to languages such as Python, C++, and Java, assembly languages are often considered the most efficient programming languages in the world. Machine code is an exception (though it itself is not considered a programming language).
Even though assembly is a general term, it has global syntax, and the object file it compiles is universally compatible. Starting from the Intel 4004 CPU, an instruction set was designed specifically for that CPU. The instruction set was definitely enough to create a computer, and that went on to inspire numerous computers to implement this technology. Also, it provided the essence to an essential terminology: the assembly language. However, as the language grew more sophisticated, a further improvement was needed, so assembly languages and machine code were separated, and assembly languages were presented at the operating system level. Of course, a converter was needed to convert Assembly into machine code, so it was assembled into an object file that is further converted into machine code.
Because assembly languages are earlier languages, I would argue that they have plenty of bugs, and they don’t show details about errors that appear. Despite being efficient, Assembly does slow down as time progresses and sometimes unstable errors, such as short-circuit and hard-drive problems (often due to circuitry), do occur. Because assembly languages’ instructions have expanded over time, they are even more unreadable, thus not many programmers have interacted with such programming languages. Assembly languages are still an important part of computer architecture, though.
The Universal Format
As a universally recognized language, a line of code in an assembly language is composed of an opcode (command) and an operand (parameter). If a syscall (a function, in technical terms) is required, the parameters required will be loaded into several registers, and the syscall is invoked by interrupting a certain process. The difference between the syntax of assembly language and machine code is only that machine code is the binary version of an assembly language. The code is converted through a one-to-one table of all possible commands.
An assembler is a compiler for an assembly language, and it encodes assembly language to an object file. The previous heading mentions the format for a line of code, but a more readable version of machine code might contain labels as a target that the execution of the program can direct to, and definition of functions — templates that contain a set of commands that the program will execute once the identifier of the function is met — that you can call. This is much like modern programming languages, and assemblers do all the work of resolving the details, sacrificing compile-time efficiency for readability while maintaining runtime efficiency.
A computer has a central processing unit (CPU), which does all the hard work, executing numerous machine language instructions per second and consisting of multiple cores. Every instruction begins with the fetch phase, which retrieves the command in the corresponding area of memory. Next, is the decode phase, which looks up the specific lookup table of the computer and extracts the corresponding information regarding the specific command, and finally is the execute phase, which executes the command according to all the information mentioned above. Further breaking down a core, you will discover multiple chips that are the random access memory (RAM, which interacts with blocks of memory), the buffer (which stores blocks of memory into the inner CPU for easy access), and the ALU (a chip responsible for performing operations with two binary numbers). There may be more components in the CPU, but the above is enough to make a computer. These components work together to create the fundamentals of machine language.
As technologies improve, machine language and assembly language may seem useless or be cast aside, but they are still part of our computers’ minds.