.global _start
.extern puts
.extern exit
.text
# This is a comment
_start:
mov $msg, %rdi # THis is a comment in a code line
call puts
call exit
.section .rodata
msg: .asciz "Hello World GAS and C!!"Assembly language is the lowest level language we can use without
writing machine code (zeros and ones) directly. It’s not really a
language but a family of languages, which are different for each type of
platform/processor. In this book, we will use the x86_64
platform, as it is the most widespread, at least for now. Whenever
possible, we will show you two versions of the programs.
The first using the standard C library and the second using system calls, although in the second case we will have to limit the functionality of the programs a bit so that they don’t become endless.
The entry point for assembly programs in GNU/Linux is
_start. The two functions we use belong to the standard C
library. puts displays a character string in the console
and exit terminates the program.
I’M A NEWBY
Most languages, compiled or interpreted, automatically include code to terminate programs, however, in assembly we have to do everything ourselves. Theexitfunction makes a system call to the operating system to tell it that the process must terminate. Otherwise, the program would continue executing with whatever the contents of memory are next, which usually ends with a segmentation fault.
Each operating system defines its own ABI, a series of
rules and formats for the execution of binary code among other things.
GNU/Linux uses the System V ABI. As far as we, as programmers, are
concerned, the part of the ABI that interests us is the one that
indicates how we should call functions and the operating system. For the
System V ABI and x86_64 platform, this is the relevant
information:
RDI,RSI,RDX,RCX,R8andR9are used to pass parameters to functions or system callsRAXis used as a return value. In the case of system calls, it is also used to indicate the number of the syscall we want to execute.
As you can see, the program loads the pointer to the string we want
to print into RDI and then calls the function.
NOW YOU KNOW WHY
You may have heard that it’s not a good practice to define functions with many parameters. As you can see, when we reach the assembly level, the more parameters there are, the more work we have to do. But what’s even worse is that when we run out of registers, the values will be stored on the stack, which is much slower to access, adding an extra penalty to the execution time of our functions.
In general, assembly language does very few things for us. However, as a trade-off, it allows us to do practically whatever we want.
To compile this program using the standard GNU toolchain, we must use the following commands:
$ as -o hello1.o hello1.s
$ ld -I/usr/bin/ld.so -lc -o hello1-asm hello1.o
The first command invokes the assembler to compile our code, which we
usually store in a file with a .s extension. Once
assembled, we must link it to produce an executable and, in this case,
also link the standard C library to be able to use the puts
and exit functions.
I’M A NEWBIE
Toolchain is the generic name given to the set of tools that are needed to produce programs for a specific platform. It usually consists of the following programs:addr2line Converts memory addresses to line numbers in source code (ADDRess to Line) ar File archiver. Used to generate static libraries (ARquiver) as Assembler (Assembler) c++filt Decodes C++ symbol names cpp C pre-processor (C Pre-Processor) elfedit Allows modifying header and properties of ELF programs gcc The C compiler (GNU C Compiler) gcov Tool for coverage testing (GNU Coverage tool) gcov-dump Tool for displaying information about program coverage gprof Tool for performance analysis (GNU Profiler) ld The linker lto-dump Used to display LTO files (Link-Time Optimisations) nm Lists symbols in objects objcopy Object file manipulation objdump Displays information about object files ranlib Generates indexes for files (static libraries) to speed up compilation readelf Displays information about ELF files strings Displays character strings in binary files size Size of the file by memory sections strip Removes unnecessary parts from executable files
The assembler version using system calls will be shown with assembler
in Intel format and using nasm as the assembler. The
program would be the following:
global _start
_start:
;; Comments start with ;
mov rax, 1 ; In line comment
mov rdi, 1
mov rsi, msg
mov rdx, size
syscall
;; Exit program
mov rax, 0x3c ; SYS_exit = 0x3c
mov rdi, 0
syscall
msg:
db 'Hello World from NASM!',0x0a
size: equ $ - msgTo implement the program with system calls, we must use two of these
calls. The SYS_write call, which allows us to display
messages on the screen if we write to standard output (file descriptor
number 1), and the SYS_exit system call, to terminate the
program cleanly.
As you can see, the ABI is the same as for function calls, with the
exception that the RAX register must be loaded with the
value of the system call we want to execute.
To compile this program with nasm, we can use the
following commands:
$ nasm -f elf64 -o hello2.o hello2.asm
$ ld -o hello2-asm hello2.o
The main difference is that now we don’t need LibC and our program is much smaller and doesn’t depend on any external library.
Unlike other languages, we can’t offer you a name and creation date. Assembly language was born with the first processor, and a new version emerges whenever a new processor is developed or improved.
Summary
- Compiled Language
- Extension:
asm/s - Line Terminator : Carriage Return
- Group Instructions with : Does not exist
- Multiline Comments : Do not exist
- Comments same line:
;or@or# - String Delimiter:
"string" - No way to write text directly
- Multiline string support: Not supported.
- Does not Support
HERE-DOCS - Entry Point:
_start