R0b0t1
2009-09-16 07:57:35
How do you highlight for different languages? I can't remember.
Anyway, this program reads in a string that represents a brainfuck program, it then compiles it into the RAM, and jumps to it like a function, running it. Theoretically you could have a thread run it, and then use a different thread to give it input.
Only works on 64bit Linux, but I'm trying to fix that (main problem is that I use the x64 calling convention to preload registers with stuff, on x86 that doesn't happen).
Anyway, this program reads in a string that represents a brainfuck program, it then compiles it into the RAM, and jumps to it like a function, running it. Theoretically you could have a thread run it, and then use a different thread to give it input.
Only works on 64bit Linux, but I'm trying to fix that (main problem is that I use the x64 calling convention to preload registers with stuff, on x86 that doesn't happen).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/user.h>
#define BIT64
#define bfcall(arr, tape, inarr, outarr) \
((int (*)(char *, char *, char *))func)(tape, inarr, outarr)
typedef int (*BFFUNC) (char*, char*, char*);
char *compile(char *f, int flen);
int main()
{
char f[] = ",.[,.]";
//0x31, 0xC0, 0xC3 //xor %eax, %eax; ret;
//0x89, 0xF8, 0xC3 //mov %edi, %eax; ret;
//0xFF, 0xF7, 0x8F, 0xC0, 0xC3 //push %edi; pop %eax; ret;
//0xB8, 0x10, 0x00, 0x00, 0x00, 0xC3 //mov $16, %eax; ret;
char *func, tape[128], inarr[128], outarr[128];
int ret = 0;
char input[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
memset(tape, 0, sizeof(tape));
memcpy(inarr, input, sizeof(input));
memset(outarr, 0, sizeof(outarr));
func = compile(f, 2048);
//edi esi edx
ret = ((BFFUNC)func)(tape, inarr, outarr);//bfcall(func, tape, inarr, outarr);
printf("%d\n%s\n", ret, outarr);
free(func);
return 0;
}
char *compile(char *f, int flen)
{
int i = 0, bcnt = 0, jmp = 0; char *func, *pp = f, *bstack[128];
if(posix_memalign((void **)&func, PAGE_SIZE, flen)) return NULL;
if(mprotect(func, 5, PROT_EXEC | PROT_WRITE)) { free(func); return NULL; }
for(; *pp && i < flen; pp++)
{
switch(*pp)
{
case '+': func[i++] = 0xFE; func[i++] = 0x07; break; // inc (%edi)
case '-': func[i++] = 0xFE; func[i++] = 0x0F; break; // dec (%edi)
case '>':
#ifdef BIT64
func[i++] = 0x48; // REX.W byte for 64bit addresses.
#endif
func[i++] = 0xFF; func[i++] = 0xC7; break; // inc %edi
case ',': func[i++] = 0xA4; // movsb
case '<': // fallthrough to dec %edi.
#ifdef BIT64
func[i++] = 0x48;
#endif
func[i++] = 0xFF; func[i++] = 0xCF; break; // dec %edi
case '.':
func[i++] = 0x8A; func[i++] = 0x07; //
func[i++] = 0x88; func[i++] = 0x02; //
#ifdef BIT64
func[i++] = 0x48;
#endif
func[i++] = 0xFF; func[i++] = 0xC2; // inc %edx
break;
case '[': bstack[bcnt++] = &func[i];
func[i++] = 0x80; func[i++] = 0x3F; func[i++] = 0x00;
func[i++] = 0x0F; func[i++] = 0x84; i += 4;
break;
case ']': func[i++] = 0x80; func[i++] = 0x3F; func[i++] = 0x00;
func[i++] = 0x0F; func[i++] = 0x85;
jmp = bstack[--bcnt] - &func[i + 4];
memcpy(&func[i], &jmp, 4); i += 4;
jmp = -(jmp + 9);
memcpy(bstack[bcnt] + 5, &jmp, 4);
break;
}
}
func[i++] = 0x31; func[i++] = 0xC0; // clear eax
func[i++] = 0x8A; func[i++] = 0x07; // move current cell to al
func[i] = 0xC3;
return func;
}