If you are writing assembly for ARM processors, make sure to check out the [GNU ARM Assembler Quick Reference](http://bel.gsi.de/scripts/gnu-arm-assy-quick-ref.pdf).
Intel vs. AT&T Syntax
Intel syntax always puts the destination address before the source address.
AT&T syntax always puts the source address before the destination address. It also requires a `%` infront of every register access, and a `$` infront of immediate operands.
The NASM assembly language is a very popular language that works on the x86 and x86-64 architectures. It has similar syntax to Intel's x86/x86-64 assembly, but it designed to be more "user friendly".
Compiling NASM Assembly
You can download the NASM compiler for Ubuntu and other Debian-like systems with:
To compile a NASM
.asm file, first convert it to an object file with the nasm program:
OR for a 64-bit object file:
This will produce an object file called
You then have two options for linking:
- Use the linker program
gcc. This automatically links against the C standard library for you.
32-bit object files:
For 64-bit object files:
Hello World (using NASM)
This Hello, World example will be as bare-bones as possible, and will not even use the
printf() function call (instead it will make a Linux system call directly).
First, we need a
.section text to tell the compiler that this is our executable code.
We then need to define an entry point for our program:
Hello, world! requires the use of a Linux system call to print the text to `stdout` (specifically,
sys_write). We will use the Linux fastcall convention which allows us to put the input arguments into registers, rather than on the stack. The system call number is placed in
eax, and the arguments in the successive registers
ecx, e.t.c. The function number for
4 (see here). We need to place the file we wish to write to in ebx, a pointer to the message (
char *) in
ecx, and the number of characters in
Note that I have assigned the registers in reverse order (starting at edx and going to eax). This is not necessary (any order would work), however this practise stems from the sequence required making a system call by pushing to the stack instead, in where this order is important. I just kept the same practise for good readability.
So, now we need to place the message in memory somewhere, and also find out it’s size, so we can fill in
<pointer to msg> and
<msg size>. We can create a data section just for this purpose:
db is a NASM instruction which stands for define bytes. It defines a sequence of bytes in memory.
equ just tells the compiler to calculate the length of the message and save it to
len (called a symbol), which can then be used in the code (it does not save the value to memory, it is similar to #define in C).
Lets use the new
msg variable in our code:
Great, everything is setup for a system call! But how do we perform a system call? In Linux, a system call is made by triggering the
0x80 interrupt, so we will do just that:
Running the above code should print
Hello, world! to stdout. But your program might then just seg fault. This is because we have not exited cleanly. To do this, we can make another sys call, this time to
All done! Run this code online at https://www.tutorialspoint.com/tpcg.php?p=qjMuBp.
Hello World With printf()
Because we want to know use a standard library function, we are going to take a slightly different approach.
test.asm file with the following contents:
Now compile and run with the following commands:
This work is licensed under a Creative Commons Attribution 4.0 International License .
- November 2017 Updates
- October 2017 Updates
- How To Add A Custom App To A Yocto Build
- October 2015 Updates
- Compiling FreeRTOS With C++