0% found this document useful (0 votes)
2 views4 pages

01 HighLevelLanguage Assembly Executable

The document explains the process of translating a simple C program into assembly language and then into machine code for different computer architectures (x86_64 and armv7l). It details the commands used to compile the code and the resulting differences in the generated assembly and executable files. Additionally, it highlights the distinctions between high-level languages and assembly languages in terms of architecture dependency and compilation capabilities.

Uploaded by

samvossenberg
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views4 pages

01 HighLevelLanguage Assembly Executable

The document explains the process of translating a simple C program into assembly language and then into machine code for different computer architectures (x86_64 and armv7l). It details the commands used to compile the code and the resulting differences in the generated assembly and executable files. Additionally, it highlights the distinctions between high-level languages and assembly languages in terms of architecture dependency and compilation capabilities.

Uploaded by

samvossenberg
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

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

You might also like