get paid to paste

bfcomp

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void pasm(const char *s, ...);
void syscall(const char *ncall, const char *a, const char *b, const char *c);
int push(int n);
int pop(void);
void print_long(const char *name);
void print_data(void);
void print_getchar(void);
void print_putchar(void);
void init_bf(void);
void out_sub(int val, char c, const char *to);
void out_add(int val, char c, const char *to);
void char_to_code(int c, int times);

void    pasm(const char *s, ...)
{
  va_list       args;

  printf("\t");
  va_start(args, s);
  vprintf(s, args);
  va_end(args);
  printf("\n");
}

#if     defined(linux) || defined(__linux)
void    syscall(const char *ncall, const char *a, const char *b, const char *c)
{
  if (strcmp("%eax", ncall)) // Here to avoid redundant movs
    pasm("movl %s, %%eax", ncall);
  if (strcmp("%ebx", a))
    pasm("movl %s, %%ebx", a);
  if (strcmp("%ecx", b))
    pasm("movl %s, %%ecx", b);
  if (strcmp("%edx", c))
    pasm("movl %s, %%edx", c);
  pasm("int $0x80");
}
#elif   defined(BSD) // the BSD style syscall isn't tested
void    syscall(const char *ncall, const char *a, const char *b, const char *c)
{
  pasm("movl %s, %%eax", ncall);
  pasm("pushl %s", c);
  pasm("pushl %s", b);
  pasm("pushl %s", a);
  pasm("subl $4, %%esp");
  pasm("int $0x80");
  pasm("addl $16, %%esp");
}
#else
# error only handles linux and bsd systems
#endif

typedef struct s_llst   t_llst;

struct          s_llst
{
  int           n;
  t_llst        *next;
};

// The labels stack
t_llst          *stack = NULL;
int             label_max = 0;

int             push(int n)
{
  t_llst        *p;

  p = malloc(sizeof(*p));
  p->n = n;
  p->next = stack;
  stack = p;
  return (n);
}

int             pop()
{
  int           tmp_n;
  t_llst        *p;

  if (stack == NULL)
    return (-1);
  tmp_n = stack->n;
  p = stack;
  stack = p->next;
  free(p);
  return (tmp_n);
}

void            print_long(const char *name)
{
  printf(".align 4\n");
  printf("%s:\n", name);
  pasm(".long 0");
}

void            print_data()
{
  printf(".data\n");
  print_long("pos_read");
  print_long("len_read");
  print_long("pos_write");
  puts("");
  pasm(".comm buf_read, 512, 32");
  pasm(".comm buf_write, 512, 32");
  puts("");
}

void            print_getchar()
{
  printf("getchar:\n");
  pasm("movl pos_read, %%eax");
  pasm("cmpl len_read, %%eax");
  pasm("jl retchar");
  syscall("$3", "$0", "$buf_read", "$512"); // The read syscall
  pasm("cmpl $0, %%eax"); // Note: that doesn't handle errors properly on bsd
  pasm("jg read_ok");
  pasm("movl $0, (%%ebp, %%esi)"); // EOF is handled as returning 0
  pasm("ret");
  printf("read_ok:\n");
  pasm("movl %%eax, len_read");
  pasm("movl $0, pos_read");
  printf("retchar:\n");
  pasm("movl pos_read, %%eax");
  pasm("movb buf_read(%%eax), %%bh");
  pasm("movb %%bh, (%%ebp, %%esi)");
  pasm("incl %%eax");
  pasm("movl %%eax, pos_read");
  pasm("ret");
}

void            print_putchar()
{
  printf("putchar:\n");
  pasm("movl pos_write, %%eax");
  pasm("incl %%eax");
  pasm("movb (%%ebp, %%esi), %%bh");
  pasm("movb %%bh, buf_write(%%eax)");
  pasm("movl %%eax, pos_write");
  pasm("cmpl $512, %%eax");
  pasm("jge flush");
  pasm("cmpb $%d, %%bh", '\n');
  pasm("je flush");
  pasm("ret");
  printf("flush:\n");
  pasm("movl pos_write, %%edx");
  pasm("incl %%edx");
  syscall("$4", "$1", "$buf_write", "%edx");
  pasm("movl $0, pos_write");
  pasm("ret");
}

void            init_bf()
{
  print_data();
  printf(".text\n");
  print_getchar();
  print_putchar();
  printf(".globl _start\n");
  printf("_start:\n");
  pasm("movl %%esp, %%ebp"); // base pointer
  pasm("subl $30000, %%esp"); // allocate space
  pasm("xorl %%eax, %%eax");
  printf("memzero:\n"); // initialize space
  pasm("movl $0, (%%ebp, %%eax, 0x4)");
  pasm("decl %%eax");
  pasm("cmpl $-7500, %%eax");
  pasm("jg memzero");
  pasm("xorl %%esi, %%esi"); // initialize counter
}

void            out_sub(int val, char c, const char *to)
{
  if (val < 0)
    out_add(-val, c, to);
  else if (val == 1)
    pasm("dec%c %s", c, to);
  else if (val > 1)
    pasm("sub%c $%d, %s", c, val, to);
}

void            out_add(int val, char c, const char *to)
{
  if (val < 0)
    out_sub(-val, c, to);
  else if (val == 1)
    pasm("inc%c %s", c, to);
  else if (val > 1)
    pasm("add%c $%d, %s", c, val, to);
}

void            char_to_code(int c, int times)
{
  if (c == '>') // handles circular memory
    {
      out_sub(times, 'l', "%esi");
      pasm("cmpl $-30000, %%esi");
      pasm("jg wrapped%d", label_max);
      pasm("addl $30000, %%esi");
      printf("wrapped%d:\n", label_max++);
    }
  else if (c == '<')
    {
      out_add(times, 'l', "%esi");
      pasm("cmpl $0, %%esi");
      pasm("jle wrapped%d", label_max);
      pasm("subl $30000, %%esi");
      printf("wrapped%d:\n", label_max++);
    }
  else if (c == '+')
    out_add(times, 'b', "(%ebp, %esi)");
  else if (c == '-')
    out_sub(times, 'b', "(%ebp, %esi)");
  else if (c == '.')
    while (times--)
      pasm("call putchar");
  else if (c == ',')
    while (times--)
      pasm("call getchar");
  else if (c == '[')
    while (times--)
      {
        printf("start%d:\n", push(label_max++));
        pasm("movb (%%ebp, %%esi), %%al");
        pasm("testb %%al, %%al");
        pasm("jz end%d", stack->n);
      }
  else if (c == ']')
    while (times--)
      {
        pasm("jmp start%d", stack->n);
        printf("end%d:\n", pop());
      }
}

int             main()
{
  int           cur_char;
  int           last_char;
  int           times_char;

  init_bf();
  times_char = 0;
  last_char = cur_char = getchar();
  do
    {
      if (cur_char == last_char)
        times_char++;
      else
        {
          char_to_code(last_char, times_char);
          last_char = cur_char;
          times_char = 1;
        }
    } while ((cur_char = getchar()) != -1);
  pasm("call flush");
  pasm("movzbl (%%ebp, %%esi), %%ebx");
  pasm("movl $1, %%eax");
  pasm("int $0x80");
  return (0);
}

Pasted: Aug 8, 2010, 8:37:46 pm
Views: 79