Cı, 866 783 bayt
Kodum 32 bit ELF çalıştırılabilir çıktısı olduğundan, herkesin kurulumunda çalışacağına söz veremem. Bilgisayarımda segfaulting durdurmak için çalıştırılabilir almak için yeterli tweaking aldı.
Bunu çalıştırmaya çalışan herkes için:
$ uname --all
Linux 4.4.0-24-generic #43-Ubuntu SMP Wed Jun 8 19:27:37 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
Bir Brainfuck programı stdin'den okunur ve derlenen ELF stdout'a yazılır.
#define P *(t++)
#define C case
#define B break
char a[30000],b[65535],f,*t=b;*c[100];**d=c;main(g){P=188;t+=4;while((f=getchar())!=-1)switch(f){C'>':P=68;B;C'<':P=76;B;C'+':P=254;P=4;P=36;B;C'-':P=254;P=12;P=36;B;C'.':P=187;t+=4;P=137;P=225;P=186;P=1;t+=3;P=184;P=4;t+=3;P=205;P=128;B;C',':P=187;P=1;t+=3;P=137;P=225;P=186;P=1;t+=3;P=184;P=3;t+=3;P=205;P=128;B;C'[':P=138;P=4;P=36;P=133;P=192;P=15;P=132;t+=4;*d=(int*)t-1;d++;B;C']':P=138;P=4;P=36;P=133;P=192;P=15;P=133;t+=4;d--;g=((char*)(*d+1))-t;*((int*)t-1)=g;**d=-g;B;}P=184;P=1;t+=3;P=187;t+=4;P=205;P=128;*(int*)(b+1)=0x8048054+t-b;long long z[]={282579962709375,0,4295163906,223472812116,0,4297064500,4294967296,577727389698621440,36412867248128,30064779550,140720308490240};write(1,&z,84);write(1,b,t-b);write(1,a,30000);}
Ungolfed
Kodun çözülmemiş sürümünde, neler olup bittiğiyle ilgili daha iyi bir fikir edinebilirsiniz. Golf kodunun sonundaki karakter dizisi ELF ve kodlanmamış koddaki program başlığının kodlamasıdır. Bu kod aynı zamanda her Brainfuck komutunun bayt koduna nasıl çevrildiğini gösterir.
#include <linux/elf.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#define MAX_BIN_LEN 65535
#define MAX_JUMPS 100
unsigned int org = 0x08048000;
unsigned char move_right[] = {0x44}; /*inc esp */
unsigned char move_left[] = {0x4c}; /*dec esp */
unsigned char inc_cell[] = {0xfe,0x04,0x24}; /*inc [esp] */
unsigned char dec_cell[] = {0xfe,0x0c,0x24}; /*dec [esp] */
unsigned char read_char[] = {0xbb,0x00,0x00,0x00,0x00, /*mov ebx, 0 */
0x89,0xe1, /*mov ecx, esp */
0xba,0x01,0x00,0x00,0x00, /*mov edx, 1 */
0xb8,0x03,0x00,0x00,0x00, /*mov eax, 3 */
0xcd,0x80}; /*int 0x80 */
unsigned char print_char[] = {0xbb,0x01,0x00,0x00,0x00, /*mov ebx, 1 */
0x89,0xe1, /*mov ecx, esp */
0xba,0x01,0x00,0x00,0x00, /*mov edx, 1 */
0xb8,0x04,0x00,0x00,0x00, /*mov eax, 4 */
0xcd,0x80}; /*int 0x80 */
unsigned char loop_start[] = {0x8a,0x04,0x24, /*mov eax, [esp] */
0x85,0xc0, /*test eax, eax */
0x0f,0x84,0x00,0x00,0x00,0x00}; /*je int32_t */
unsigned char loop_end[] = {0x8a,0x04,0x24, /*mov eax, [esp] */
0x85,0xc0, /*test eax, eax */
0x0f,0x85,0x00,0x00,0x00,0x00}; /*jne int32_t */
unsigned char call_exit[] = {0xb8,0x01,0x00,0x00,0x00, /*mov eax, 1 */
0xbb,0x00,0x00,0x00,0x00, /*mov ebx, 0 */
0xcd,0x80}; /*int 0x80 */
unsigned char prelude[] = {0xbc,0x00,0x00,0x00,0x00}; /*mov esp, int32_t*/
unsigned char tape[100];
int main(){
unsigned char text[MAX_BIN_LEN];
unsigned char *txt_ptr = text;
int32_t *loop_jmps[MAX_JUMPS];
int32_t **loop_jmps_ptr = loop_jmps;
Elf32_Off entry;
entry = org + sizeof(Elf32_Ehdr) + 1 * sizeof(Elf32_Phdr);
memcpy(txt_ptr,prelude,sizeof(prelude));
txt_ptr += sizeof(prelude);
char input;
while((input = getchar()) != -1){
switch(input){
case '>':
memcpy(txt_ptr,move_right,sizeof(move_right));
txt_ptr += sizeof(move_right);
break;
case '<':
memcpy(txt_ptr,move_left,sizeof(move_left));
txt_ptr += sizeof(move_left);
break;
case '+':
memcpy(txt_ptr,inc_cell,sizeof(inc_cell));
txt_ptr += sizeof(inc_cell);
break;
case '-':
memcpy(txt_ptr,dec_cell,sizeof(dec_cell));
txt_ptr += sizeof(dec_cell);
break;
case '.':
memcpy(txt_ptr,print_char,sizeof(print_char));
txt_ptr += sizeof(print_char);
break;
case ',':
memcpy(txt_ptr,read_char,sizeof(read_char));
txt_ptr += sizeof(read_char);
break;
case '[':
memcpy(txt_ptr,loop_start,sizeof(loop_start));
txt_ptr += sizeof(loop_start);
*loop_jmps_ptr = (int32_t*) txt_ptr - 1;
loop_jmps_ptr++;
break;
case ']':
memcpy(txt_ptr,loop_end,sizeof(loop_end));
txt_ptr += sizeof(loop_end);
loop_jmps_ptr--;
int32_t offset = ((unsigned char*) (*loop_jmps_ptr + 1)) - txt_ptr;
*((int32_t*)txt_ptr - 1) = offset;
**loop_jmps_ptr = -offset;
break;
}
}
memcpy(txt_ptr,call_exit,sizeof(call_exit));
txt_ptr += sizeof(call_exit);
*(int32_t*)(text + 1) = entry + (txt_ptr - text);
Elf32_Ehdr ehdr = {
{0x7F,'E','L','F',ELFCLASS32,ELFDATA2LSB,EV_CURRENT,0,0,0,0,0,0,0,0,0},
ET_EXEC,
EM_386,
EV_CURRENT,
entry,
sizeof(Elf32_Ehdr),
0,
0,
sizeof(Elf32_Ehdr),
sizeof(Elf32_Phdr),
1,
0,
0,
SHN_UNDEF,
};
Elf32_Phdr phdr = {
PT_LOAD,
0,
org,
org,
sizeof(Elf32_Ehdr) + sizeof(Elf32_Phdr) + (txt_ptr - text),
sizeof(Elf32_Ehdr) + sizeof(Elf32_Phdr) + (txt_ptr - text),
PF_R | PF_X | PF_W,
0x1000,
};
int out = open("a.out",O_CREAT|O_TRUNC|O_WRONLY,S_IRWXU);
write(out,&ehdr,sizeof(Elf32_Ehdr));
write(out,&phdr,sizeof(Elf32_Phdr));
write(out,text,txt_ptr-text);
write(out,tape,sizeof(tape));
close(out);
}
Kendini Değiştiren BrainFuck
Baytlardan tasarruf etmek için, derleyicimin bandı bir .bss
bölüme veya böyle süslü bir şeye tahsis edilmemiştir . Bunun yerine, bant Brainfuck programının derlenmiş bayt kodundan hemen sonra yazılan 30.000 boş bayttır. Bunu bilmek ve derleyici tarafından oluşturulan bayt kodunun farkında olmak, çalışma zamanında bayt kodu oluşturabileceğiniz veya değiştirebileceğiniz anlamına gelir. Bu 'özelliğin' basit bir örneği, kendi çıkış değerini ayarlayan bir Brainfuck programıdır.
<<<<<<+
Program, bandın sol kenarından bayt koduna çıkış kodunun normalde 0 olduğu noktaya kadar gider. Bu baytın artırılması, program sonunda çıkıldığında çıkış kodunun 0 yerine 1 olarak ayarlanmasına neden olur. Kalıcı olarak, bu Brainfuck'ta sistem düzeyinde programlama yapmak için kullanılabilir.