From High Level Language to readable machine code (assembly
language) to real machine code (0’s and 1’s)
We start with a very simple piece of high level langue code (ANSI-C code), saved in the file sum.c
#include <stdio.h>
int main()
{
int a = 5;
int b = 10;
int c = a + b;
printf("The value of c is %d\n", c);
return 0;
}
High Level Language => assembly language
We will first translate the C-program into readable machine code (=assembly language) with a
compiler (gcc) on two computers with different architectures:
x86_64 architecture (AMD Ryzen 7 5800U) runnning 64-bit Ubuntu linux
armv7l architecture (Raspberry PI 3B+) running 32-bit Raspbian OS:q!
On both systems the same command is used to achieve this:
gcc -S sum.s sum.c
The file sum.s is created and contains the assembly code generated specific for the architecture we
are running on.
x86_64 assembly code Armv7l assembly code
.file "sum.c" .arch armv6
.text .eabi_attribute 28, 1
.globl add .eabi_attribute 20, 1
.type add, @function .eabi_attribute 21, 1
add: .eabi_attribute 23, 3
.LFB0: .eabi_attribute 24, 1
.cfi_startproc .eabi_attribute 25, 1
endbr64 .eabi_attribute 26, 2
pushq %rbp .eabi_attribute 30, 6
.cfi_def_cfa_offset 16 .eabi_attribute 34, 1
.cfi_offset 6, -16 .eabi_attribute 18, 4
movq %rsp, %rbp .file "sum2.c"
.cfi_def_cfa_register 6 .text
movl %edi, -4(%rbp) .section .rodata
movl %esi, -8(%rbp) .align 2
movl -4(%rbp), %edx .LC0:
movl -8(%rbp), %eax .ascii "The value of c is %d\012\000"
addl %edx, %eax .text
Computer Architecture @ Thomas More - Campus De Nayer 1
popq %rbp .align 2
.cfi_def_cfa 7, 8 .global main
ret .arch armv6
.cfi_endproc .syntax unified
.LFE0: .arm
.size add, .-add .fpu vfp
.section .rodata .type main, %function
.LC0: main:
.string "The result is %d\n" @ args = 0, pretend = 0, frame = 16
.text @ frame_needed = 1,
.globl main uses_anonymous_args = 0
.type main, @function push {fp, lr}
main: add fp, sp, #4
.LFB1: sub sp, sp, #16
.cfi_startproc mov r3, #5
endbr64 str r3, [fp, #-8]
pushq %rbp mov r3, #10
.cfi_def_cfa_offset 16 str r3, [fp, #-12]
.cfi_offset 6, -16 ldr r2, [fp, #-8]
movq %rsp, %rbp ldr r3, [fp, #-12]
.cfi_def_cfa_register 6 add r3, r2, r3
subq $16, %rsp str r3, [fp, #-16]
movl $10, -12(%rbp) ldr r1, [fp, #-16]
movl $20, -8(%rbp) ldr r0, .L3
movl -8(%rbp), %edx bl printf
movl -12(%rbp), %eax mov r3, #0
movl %edx, %esi mov r0, r3
movl %eax, %edi sub sp, fp, #4
call add @ sp needed
movl %eax, -4(%rbp) pop {fp, pc}
movl -4(%rbp), %eax .L4:
movl %eax, %esi .align 2
leaq .LC0(%rip), %rax .L3:
movq %rax, %rdi .word .LC0
movl $0, %eax .size main, .-main
call printf@PLT .ident "GCC: (Raspbian 8.3.0-6+rpi1)
movl $0, %eax 8.3.0"
leave .section .[Link]-stack,"",
.cfi_def_cfa 7, 8 %progbits
ret
.cfi_endproc
.LFE1:
.size main, .-main
.ident "GCC: (Ubuntu 11.3.0-
1ubuntu1~22.04) 11.3.0"
.section .[Link]-
stack,"",@progbits
.section .[Link],"a"
.align 8
.long 1f - 0f
Computer Architecture @ Thomas More - Campus De Nayer 2
.long 4f - 1f
.long 5
0:
.string "GNU"
1:
.align 8
.long 0xc0000002
.long 3f - 2f
2:
.long 0x3
3:
.align 8
4:
These are two completely different files, each of them specific for one architecture.
Assembly language => binary machine code (executable file)
On both systems again an identical command is used to achieve this:
gcc -o sum sum.s
The option -o sum creates the executable file sum. When omitted, an executable named [Link]
(default executable name) is created.
To run the newly created program just type:
./sum
and the output
The value of c is 15
will be shown on the screen.
When you look at the executables on both machines you will notice that they differ, starting with
their size (when you run the ls- l command).
Another way to get additional information about any file on a linux/unix system is with the
command “file”. We will run it on both machines to get more information about our executables.
On the x86_64 architecture:
file sum
sum: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked,
interpreter /lib64/[Link].2,
BuildID[sha1]=d20b165341263e62cdd70e4062e582569f21fcd0, for GNU/Linux 3.2.0, not
stripped
On the armv7l (Raspberry PI):
file sum
Computer Architecture @ Thomas More - Campus De Nayer 3
sum: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked,
interpreter /lib/[Link].3, for GNU/Linux 3.2.0,
BuildID[sha1]=62a8b386cbef43f21d63363f800494a6f6e87650, not stripped
High Level Language => binary machine code (executable file)
And we can go immediately from high level language to an executable, without creating a readable
assembly file. This is the usual way to compile and link C-code:
gcc -o sum sum.c
Assembly code (and binary machine code):
Is the language to talk to a specific computer architecture (it sits closest to the
hardware as possible).
It will only run on a CPU of that computer architecture. (It will only run on a CPU
that understands this machine code)
A high level language:
Is independent of the computer architecture (it sits further away from the hardware)
It can be compiled (translated) to run on many different computer architectures, if a
usable compiler exists for the high level language.
Computer Architecture @ Thomas More - Campus De Nayer 4