A Realization on Low and High Level Languages

If you write code, you’re probably familiar with the concept of high and low level languages. In technical terms, low level means closer to the machine, like assembly languages or machine code. Higher level in technical terms means further from the machine like C, JavaScript, Swift, and so on.

However, this shouldn’t be the case. Speaking of high and low levels in the context of how close a language is to computer architecture is quite a narrow view point on the world.

Rather, in the context of “real systems”, this distinction should be reversed. In other words, C, JavaScript, and Swift are lower-level languages. Meanwhile, assembly and machine code are higher-level languages.

For instance, if we’re writing a pseudo random number generator, which language do you think gives you a better understanding about the process of how random numbers are generated?

x86-64 Assembly


rotl:
        push    rbp
        mov     rbp, rsp
        mov     QWORD PTR [rbp-8], rdi
        mov     DWORD PTR [rbp-12], esi
        mov     eax, DWORD PTR [rbp-12]
        mov     rdx, QWORD PTR [rbp-8]
        mov     ecx, eax
        rol     rdx, cl
        mov     rax, rdx
        pop     rbp
        ret

xoshiro_256_next:
        push    rbp
        mov     rbp, rsp
        push    rbx
        sub     rsp, 24
        mov     QWORD PTR [rbp-32], rdi
        mov     rax, QWORD PTR [rbp-32]
        add     rax, 8
        mov     rdx, QWORD PTR [rax]
        mov     rax, rdx
        sal     rax, 2
        add     rax, rdx
        mov     esi, 7
        mov     rdi, rax
        call    rotl
        mov     rdx, rax
        mov     rax, rdx
        sal     rax, 3
        add     rax, rdx
        mov     QWORD PTR [rbp-16], rax
        mov     rax, QWORD PTR [rbp-32]
        add     rax, 8
        mov     rax, QWORD PTR [rax]
        sal     rax, 17
        mov     QWORD PTR [rbp-24], rax
        mov     rax, QWORD PTR [rbp-32]
        add     rax, 16
        mov     rcx, QWORD PTR [rax]
        mov     rax, QWORD PTR [rbp-32]
        mov     rdx, QWORD PTR [rax]
        mov     rax, QWORD PTR [rbp-32]
        add     rax, 16
        xor     rdx, rcx
        mov     QWORD PTR [rax], rdx
        mov     rax, QWORD PTR [rbp-32]
        add     rax, 24
        mov     rcx, QWORD PTR [rax]
        mov     rax, QWORD PTR [rbp-32]
        add     rax, 8
        mov     rdx, QWORD PTR [rax]
        mov     rax, QWORD PTR [rbp-32]
        add     rax, 24
        xor     rdx, rcx
        mov     QWORD PTR [rax], rdx
        mov     rax, QWORD PTR [rbp-32]
        add     rax, 8
        mov     rcx, QWORD PTR [rax]
        mov     rax, QWORD PTR [rbp-32]
        add     rax, 16
        mov     rdx, QWORD PTR [rax]
        mov     rax, QWORD PTR [rbp-32]
        add     rax, 8
        xor     rdx, rcx
        mov     QWORD PTR [rax], rdx
        mov     rax, QWORD PTR [rbp-32]
        mov     rdx, QWORD PTR [rax]
        mov     rax, QWORD PTR [rbp-32]
        add     rax, 24
        mov     rax, QWORD PTR [rax]
        xor     rdx, rax
        mov     rax, QWORD PTR [rbp-32]
        mov     QWORD PTR [rax], rdx
        mov     rax, QWORD PTR [rbp-32]
        add     rax, 16
        mov     rax, QWORD PTR [rax]
        mov     rdx, QWORD PTR [rbp-32]
        add     rdx, 16
        xor     rax, QWORD PTR [rbp-24]
        mov     QWORD PTR [rdx], rax
        mov     rax, QWORD PTR [rbp-32]
        add     rax, 24
        mov     rax, QWORD PTR [rax]
        mov     rdx, QWORD PTR [rbp-32]
        lea     rbx, [rdx+24]
        mov     esi, 45
        mov     rdi, rax
        call    rotl
        mov     QWORD PTR [rbx], rax
        mov     rax, QWORD PTR [rbp-16]
        mov     rbx, QWORD PTR [rbp-8]
        leave
        ret
        

C


#include <stdint.h>

static inline uint64_t rotl(const uint64_t x, int k) {
  return (x << k) | (x >> (64 - k));
}

uint64_t xoshiro_256_next(uint64_t s[4]) {
  const uint64_t result = rotl(s[1] * 5, 7) * 9;
  const uint64_t t = s[1] << 17;

  s[2] ^= s[0];
  s[3] ^= s[1];
  s[1] ^= s[2];
  s[0] ^= s[3];
  s[2] ^= t;
  s[3] = rotl(s[3], 45);
  return result;
}
        

I would imagine that you find that the C code describes the process of generating a random number more clearly. In other words, the C code describes reality more than x86 assembly.

Take a line from the assembly example.

mov     rax, rdx

mov is a move instruction, and rax and rdx are registers. As a whole, a move instruction can be applied in an infinite number of programs, and rax and rdx will also be a part of those infinite numbers of programs. In other words, a move instruction is very high level because it doesn’t describe the domain specific processes of any particular program. It is therefore detached from reality.

Notice how the concept of registers and instructions are only directly relevant in the context of the assembly example. We don’t need to talk about these things in C, because they are ultimately irrelevant (only in the sense of understanding, not execution) to the larger process of generating a random number. The C code is closer to reality because it describes such reality more accurately from an understandings stand point.

In assembly, because we’re so focused on primitive details like registers and instructions, we easily miss the larger picture. We therefore miss reality.

To conclude here, if we want to build great systems, we need to optimize for understanding and reasoning about our systems. Computer architecture is an implementation detail that is largely detached from reality as it says nothing about our systems on its own. Sticking closer to computer architecture may produce faster and more performant programs, but it is often detached from the deeper truth of what we directly create.

All in all, lower level means providing both full and real awareness of the true reality of our systems, and higher level detaches itself from that in order to focus more on abstractions. In this sense, Assembly is higher level than C.

To end, in this exploration I stayed close to existing languages that are used in the mainstream. I suppose one could therefore ask about a language so low level that it describes and enhances reality perfectly, and how that would look and operate. That is, something that indeed may exist in a primitive form.

— 6/29/25