Linux Assembly

So I’ve recently switched to my first non-(usb live) Linux using Ubuntu. I wiped my whole unresizable Vista partition for this. Using assembly in Linux quite different but for the better. It already has a built-in GNU toolchain which also includes the GNU Assembler. The AT&T syntax is more readable than Intel and there’s also an interrupt you can use for kernel calls (unlike Windows where you must call DLLs).

So this is what I’ve learned so far…
The interrupt for the kernel calls in Linux is 0x80. To view the functions in this interrupt, look at /usr/include/asm/unistd_32.h (I think it’s unistd_64.h for 64-bit computers). You’ll see a list of #define’s that look like this in the beginning of the file:

#ifndef _ASM_X86_UNISTD_32_H
#define _ASM_X86_UNISTD_32_H

/*
 * This file contains the system call numbers.
 */

#define __NR_restart_syscall      0
#define __NR_exit		  1
#define __NR_fork		  2
#define __NR_read		  3
#define __NR_write		  4
#define __NR_open		  5
#define __NR_close		  6
#define __NR_waitpid		  7
#define __NR_creat		  8
#define __NR_link		  9
#define __NR_unlink		 10
#define __NR_execve		 11
#define __NR_chdir		 12

The function number goes into eax and the parameters start at ebx, then to ecx, edx, esi and edi. To know the parameters for each syscall, look at the man pages in section 2. For example, to see the arguments for the write function run this command:

man 2 write

So this should be the synopsis:

#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);

This function writes out up to [u]count[/u] bytes from [u]buf[/u] into file referenced by file descriptor [u]fd[/u]. Using this function, you can print to the console since Linux also provides these 3 global file descriptors:

  • 0 = stdin
  • 1 = stdout
  • 2 = stderr

So here’s my first hello world assembly program:

.text
.globl _start
_start:
movl $4,%eax    # ssize_t write
movl $1,%ebx    # int fd
movl $msg,%ecx  # const void *buf
movl $13,%edx   # size_t count
int $0x80
movl $1,%eax    # exit
movl $0,%ebx    # int status
int $0x80

.data
msg: .ascii "Hello world!\n"

Assuming this is hello.asm; to assemble and link, run the following commands:

as -o hello.o hello.asm
ld -o hello hello.o

Then to run it:

./hello

So we have some assembler directives used here. .text defines our text section of our program where we put our executable code. Like C programs that start at main, programs assembled with gas start at the address labeled “_start”. So before we define our _start label, we declare it as globl, which I’m not entirely sure, but I think it makes this symbol visible to other programs that are linked with it. Comments start with # or /* & */ for multiline comments. GAS uses AT&T syntax asm so instead of “instruction dest,src” we have “instruction src,dest”. Literal values prefixed with $ and registers prefixed with %. .ascii lets me define string literals in quotes, I may also use common escape sequences found in C.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: