How To: Beginners x86 Linux Assembly

Beginners x86 Linux Assembly

Beginners x86 Linux Assembly

Hello everyone! This is my first attempt at a tutorial here. There are a couple great assembly tutorials here, and I wanted to toss my coin in the fountain.

I figured, the more tuts the better, as I had trouble learning assembly in the beginning and had to read alot of tutorials. I am by no means an expert, but I think I can help a few beginners out. We will be using the Netwide Assembler (NASM), probably Gnu Debugger (GDB), and a Linux distro. This tutorial will be on x86 32 bit assembly using intel syntax. So for now, we will cover some basic concepts...

Memory and CPU:

I will not go into too much, if any detail into how the RAM and CPU actually "work". That is, this is not going to be a physics based tutorial. We will look at these things from a programmers perspective. RAM and memory are often used to mean the same thing. We are not talking about hard drive memory or any long term storage, this is the memory that programs use for short term computations. We can store all our data in memory, and use the CPU to actually compute things. In 32bit assembly, memory can be thought of as a series of blocks that can hold data. Each block is 32bits in length, and therefore can hold anything 32bits in size or under. A bit is quantifiable as an on or off value. This relates to binary, and how we hold data that way. We will go into more detail as we go further, but I don't want to barrage you with theory quite yet. We will probably have to go over the base 16 counting system (hexadecimal) as we go further as well.

Registers:

Registers are like the pockets of the cpu. We can use them to store data without going to memory. Accessing data in a register is usually faster than accessing data in a memory address. Registers are basically containers, and they can vary in purpose.

Alright, it seems we covered just enough to write an inital "hello world" type program to get your feet a bit wet. Our coverage of theory will grow as we go on, but for now, let's test your tools with a tiny program. Let's quickly cover the parts of a NASM program source file. The .text segment stores our actual instructions to the CPU; the logic of the program. The .data section is where we declare constant data. This is data we have already defined, such as a string. The .bss section is where can set a certain amount of memory to be allocated so we can store data there later. There is one more thing for you to know before we write the extremely simple program... we may use the kernel to do certain tasks, or syscalls. Here we will perform the syscall for exiting the program. In order to execute the syscall, we will store some parameters in some registers, then use int 0x80, which will call the kernel to execute a task. Here is the source code,

section .text
global _start
_start: ; this is a comment
mov ebx,0 ; stores the value zero in ebx, the exit code
mov eax,1 ; syscall number for exiting
int 0x80 ; calling the kernel

Pretty small and simple so far... Let's take a quick look this code.

We have only defined our section.text section because we will not be storing any data in memory. We have included "global start" for the loader. We will talk more about the details of the compilation process later. The instuction "mov ebx,0" stores the value 0 in the ebx register. This a parameter to the exit syscall, our exit code to be exact. "mov eax,1" stores the value 1 in the eax register, the register used to hold syscall numbers. The number 1 corresponds to the exit syscall, which exits our program. Then we use "int 0x80" to call the kernel for the exit. To compile this, save this source as filename.asm, then execute the following commands in the same directory.

nasm -f elf -F dwarf file_name.asm
ld -m elf_i386 -o file_name filename.asm

If you are on a 64bit machine, the "elf_i386" will specify to compile a 32 bit executable file. The rest of the flags on these commands will make sure that debugging info is included, which will come in use later. After executing the binary, you will find it does nothing. Congrats, it works! Later on we will learn more and probably use GDB to help us understand what is really going on in memory. For now, I just wanted to give you a super light primer and make sure your tools are working. I'm not sure of the exact frequency of these tutorials, but I will try to make more soon. Thanks for reading!

3 Comments

There is something I didn't really understand about x86 not related to this tutorial. Can you explain real mode addressing and protected mode addressing?

That's funny you say that, because I'm actually trying to learn some of that for writing code to work on boot. Yeah, if I learn , I will surely write on it :)

Share Your Thoughts

  • Hot
  • Latest