Assembly language

Updated: 12/31/2022 by Computer Hope
Stack of blocks with programming languages printed on them.

Sometimes called assembly or ASM, an assembly language is a low-level programming language.

Programs written in assembly languages are compiled by an assembler. Every assembler has its own assembly language, which is designed for one specific computer architecture.

Why is ASM useful?

Machine language is a series of numbers, which is not easy for humans to read. Using ASM, programmers can write human-readable programs that correspond almost exactly to machine language.

The disadvantage is that everything the computer does must be described explicitly, in precise detail. The advantage is that the programmer has maximum control over what the computer is doing.

Why is ASM a "low-level" language?

Assembly is called a low-level programming language because there's (nearly) a one-to-one relationship between what it tells the computer to do, and what the computer does. In general, one line of an assembly program contains a maximum of one instruction for the computer.

How is ASM different from a "high-level" language?

High-level languages provide abstractions of low-level operations which allow the programmer to focus more on describing what they want to do, and less on how it should be done. Programming this way is more convenient and makes programs easier to read at the sacrifice of low-level control.

Programs written in high-level languages never match the raw speed and efficiency of programs written in assembly. Examples of high-level languages include Python, Java, JavaScript, Clojure, and Lisp.

What is a "mid-level" language?

Mid-level languages or lower-level languages provide some high-level abstractions to make the programmer's life easier, while still providing access to low-level operations. They are used to write operating systems, so they are sometimes called system programming languages.

Programs written in mid-level languages can perform as well, or nearly as well, as programs written in assembly language. Examples of mid-level programming languages include C, C++, Ada, Nim, and Rust.

Is ASM portable?

No. Because assembly languages are tied to one specific computer architecture, they are not portable. A program written in one assembly language would need to be completely rewritten for it to run on another type of machine.

Portability is one of the main advantages of higher-level languages. The C programming language is often called "portable assembly" because C compilers exist for nearly every modern system architecture. A program written in C may require some changes before it will compile on another computer, but the core language is portable.

Generally, the higher-level a language is, the fewer changes need to be made for it to run on another architecture. The lowest-level languages — machine language and assembly language — are not portable.

Example: Hello, World! in 32-bit assembly, for Windows

Here is "Hello, World" written for a 32-bit Intel processor. It also runs on a 64-bit processor. We will compile and run it on Windows 10.

    global  _main
    extern  _printf
    section .text
_main:
    push    message
    call    _printf
    add     esp, 4
    ret
message:
    db  'Hello, World!', 10, 0

To begin, open Notepad. Copy and paste the code above into a new text file, and save the file as hello.asm.

To compile the assembly, we use NASM, the Netwide Assembler. It can be downloaded at the NASM site.

nasm -f win32 hello.asm

When you run this command, NASM creates an object file. An object file contains machine code, but is not quite an executable file. Our object file is called hello.obj.

To create the executable, we use the 32-bit version of MinGW (Minimal GNU for Windows) which provides the gcc compiler. It can be downloaded at MinGW site.

gcc -o hello.exe hello.obj
hello
Hello, World!

Example: Hello, World! in 64-bit assembly, for Linux

Here is "Hello, World" written for a 64-bit Intel processor. We will compile and run it on 64-bit Linux.

        extern printf           ; the C printf function, to be called
        section .data           ; Data section, initialized variables
msg:    db "Hello, world!", 0   ; C string terminates with 0
fmt:    db "%s", 10, 0          ; The printf format, "\n",'0'
        section .text           ; Begin code section
        global main             ; the standard gcc entry point
main:                           ; the program label for the entry point
        push    rbp             ; set up stack frame, must be aligned
        mov     rdi,fmt
        mov     rsi,msg
        mov     rax,0           ; can also be: xor rax,rax
        call    printf          ; Call C printf function
        pop rbp                 ; restore stack
        mov rax,0               ; normal, no error, return value
        ret                     ; return

Copy and paste this program into a new file called hello.asm.

Then, compile the assembly with NASM, which you can install with your package manager. For instance, on Ubuntu or Debian, you can install NASM using apt:

sudo apt update && sudo apt install nasm

Run this command to create your object file:

nasm -f elf64 hello.asm

The object file is named hello.o.

Next, use gcc to link this object file to the necessary libraries on your computer, and compile it to an executable file called hello:

gcc hello.o -o hello

Lastly, run the executable file:

./hello
Hello, world!

For reference, this is the same program, written in C:

#include <stdio.h>
int main()
{
  char msg[] = "Hello world\n";
  printf("%s\n",msg);
  return 0;
}

2GL, Assembler, Low-level language, Machine language, Programming terms, TLA