Created
May 30, 2014 13:28
-
-
Save trevd/2feb2eb504e2884f2dec to your computer and use it in GitHub Desktop.
simple cat x86 assembly
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define __ASSEMBLY__ | |
#include <asm/unistd.h> | |
#include <asm/mman.h> | |
#include <asm/types.h> | |
# make shit more readable - there'll be no "magic numbers" here | |
#define NULL 0 | |
# syscall interupt | |
#define SYSCALL 0x80 | |
# stdin , out and err | |
#define STDIN_FILENO 0 | |
#define STDOUT_FILENO 1 | |
#define STDERR_FILENO 2 | |
#file access flags | |
#define O_RDONLY 0 | |
# Pogram exit codes | |
#define EXIT_SUCCESS 0 | |
#define EXIT_FAILURE_LSTAT 1 | |
#define EXIT_FAILURE_OPEN 2 | |
#define EXIT_FAILURE_MMAP 3 | |
# mmap related | |
#define MAP_OFFSET_ZERO 0 | |
#define MAX_ERRNO 4095 | |
.section .bss | |
# reserve 96 bytes for struct_stat | |
.lcomm struct_stat,96 | |
# st_size is 44 bytes into the structure | |
#define st_size struct_stat+44 | |
# reserve 4 bytes for out file handle | |
.lcomm fd, 4 | |
# reserve 4 bytes for the pointer to the memory mapped file | |
.lcomm mapped_file_ptr, 4 | |
# text section - this is where our code lives | |
.section .text | |
# make our entry point knowing to the linker | |
.global _start | |
# Program entry point | |
_start: | |
# Prologue setup a stack frame | |
push %ebp | |
mov %esp, %ebp | |
# int lstat(const char *path, struct stat *buf); | |
# lstat( 12(%ebp) , struct_stat ) | |
mov $struct_stat, %ecx | |
mov 12(%ebp), %ebx | |
mov $__NR_lstat64, %eax | |
int $SYSCALL | |
# test eax and jump if the signed flag is set | |
# i.e eax = -1 | |
test %eax, %eax | |
js exit_cannot_lstat_file | |
# int open(const char *pathname, int flags); | |
# open ( 12(%ebp) , O_RDONLY ) | |
mov $O_RDONLY, %ecx | |
mov 12(%ebp), %ebx | |
mov $__NR_open, %eax | |
int $SYSCALL | |
# test eax and jump if the signed flag is set | |
# i.e eax = -1 | |
test %eax, %eax | |
js exit_cannot_open_file | |
# stash the open file handle away. | |
# we could probably push this onto the stack .. meh! | |
mov %eax, fd | |
# void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset); | |
# mmap( NULL,st_size,PROT_READ,MAP_SHARED,fd,MAP_OFFSET_ZERO) | |
# mmap uses the stack for it arguments. | |
#mov $MAP_OFFSET_ZERO, %eax | |
#sarl $12, %eax | |
push $MAP_OFFSET_ZERO #%eax | |
push fd | |
push $MAP_PRIVATE | |
push $PROT_READ | |
push st_size | |
push $NULL | |
mov %esp, %ebx | |
mov $__NR_mmap, %eax | |
int $SYSCALL | |
# on x86_64 it seems like eax starts with ffff... | |
# testing this full value will set the signed flag | |
# just test ax instead... | |
# There's Probably a better way to do this but I don't know it.. yet | |
cmp $-MAX_ERRNO, %eax | |
ja exit_cannot_mmap_file | |
# stash the mapped file pointer | |
mov %eax, mapped_file_ptr | |
# tidy up the stack by moving the stack pointer back 24 bytes | |
add $24, %esp | |
# move argv[1] into eax for strlen | |
#mov 12(%ebp), %eax | |
#call _strlen | |
# ssize_t write(int fd, const void *buf, size_t count); | |
# write(STDOUT_FILENO, mapped_file_ptr, size_t st_size) | |
mov st_size, %edx | |
mov mapped_file_ptr, %ecx | |
mov $STDOUT_FILENO, %ebx | |
mov $__NR_write, %eax | |
int $SYSCALL | |
# int munmap(void *addr, size_t length); | |
# munmap(mapped_file_ptr, st_size); | |
mov st_size, %ecx | |
mov mapped_file_ptr, %ebx | |
mov $__NR_munmap, %eax | |
int $SYSCALL | |
# int close(int fd); | |
# close(fd); | |
mov fd, %ebx | |
mov $__NR_close, %eax | |
int $SYSCALL | |
exit_success: | |
mov $EXIT_SUCCESS,%ebx | |
jmp exit | |
exit_cannot_lstat_file: | |
mov $EXIT_FAILURE_LSTAT,%ebx | |
jmp exit | |
exit_cannot_open_file: | |
mov $EXIT_FAILURE_OPEN, %ebx | |
jmp exit | |
exit_cannot_mmap_file: | |
# int close(int fd); | |
# close(fd); | |
mov fd, %ebx | |
mov $__NR_close, %eax | |
int $SYSCALL | |
mov $EXIT_FAILURE_MMAP,%ebx | |
jmp exit | |
exit: | |
# void exit(int status); | |
# see above for EXIT_ status | |
mov $__NR_exit, %eax | |
pop %ebp | |
int $SYSCALL | |
#undef __ASSEMBLY__ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment