source: trunk/Examples/Others/bfcl.bf

Last change on this file was 11, checked in by chronos, 12 years ago
  • Added: Some other examples from web.
File size: 29.0 KB
Line 
1This is version 0_1 of bfcl
2
3bfcl is a BrainFuck compiler for Linux written itself in BrainFuck
4It reads the input from stdin and outputs a Linux ELF binary on stdout
5Currently no optimization at all is done (which is another reason why
6this thing is so sloooooooow on my system :) but that is planned for
7version 0_2
8
9Conventions assumed in this program:
10fields are one byte long and decreasing zero is possible
11
12Conventions in the binaries compiled with bfcl:
13a) fields are one byte long
14b) there are 30 000 fields
15c) moving the pointer outside this area will lead to your computer
16 catching fire;
17 nothing is done to prevent you from doing that however
18d) when end of file is encountered the program stores whatever
19 the Linux syscall returns (I believe it's zero but I'm too lazy to
20 check)
21e) No checks are made on matching parentheses; maybe for version 0_3 :)
22
23And yes; I know the code is far from pretty; far from optimized; and not
24very well documented; but I'm sending it out anyway because the longer I
25stare at it the more my head hurts
26
27Final word of thanks: many ideas are shamelessly stolen from Brian
28Raiter's 171 byte BF compiler available from www_muppetlabs_com/~breadbox/
29
30For questions and comments you can reach me at
31vissers@theochem dot kun dot nl
32You will forgive me for not typing the dots :)
33
34Ge Vissers
3517 april 2003
36
37**************************************************************************
38
39>>>>>>> reserve some extra space
40 so we can shift the program later
41
42Read the program
43
44Reading a character is a bit of a nuisance since different compilers
45use different strategies:
46a) leave byte unchanged
47b) set byte to zero
48c) set byte to 0xff
49I *believe* the following code snippets catches all three possibilities above
50so that the program ends on either a null or a 0xff byte
51
52>- set character to 0xff
53, read a character
54[<+>->+<] copy byte to previous and next field
55>[+<]> if byte is not zero
56 add one to it
57[ if it is still not zero
58 [-]< clear the copy
59 +++++[<-------->-]<--- subtract plus from input
60 [ if char is not plus
61 - subtract 1 from char
62 [ if char is not comma
63 - subtract 1 from char
64 [ if char is not minus
65 - subtract 1 from char
66 [ if char is not dot
67 -------------- subtract 14 from char
68 [ if char is not left angle
69 -- subtract 2 from char
70 [ if char is not right angle
71 >+++[<---------->-]<+ subtract 29 from char
72 [ if char is not left bracket
73 -- subtract 2 from char
74 [ if char is not right bracket
75 <--------> set opcode to minus 8
76 [-] clear character
77 ]
78 <+> increase opcode
79 ] end if (char is not left bracket)
80 <+> increase opcode
81 ] end if (char is not right angle)
82 <+> increase opcode
83 ] end if (char is not left angle)
84 <+> increase opcode
85 ] end if (char is not dot)
86 <+> increase opcode
87 ] end if (char is not minus)
88 <+> increase opcode
89 ] end if (char is not comma)
90 <+> increase opcode
91 ] end if (char is not plus)
92 <+ increase opcode
93 [ if opcode is not zero
94 > move to next field
95 ] end if (opcode is not zero)
96 >>-, read in a new character
97 [<+>->+<] copy to previous and next field
98 >[+<]> if not null check if it's 0xff
99] end while not EOF
100
101<<[+] clear possible 0xff
102
103>>++++++++[<++++++++++>-]<++++< 84 bytes for ELF header
104>++++++++++++< 12 bytes to initialize program
105>++++++< 6 bytes to end program
106
107Calculate file size
108
109<<[<]> move to first opcode
110[ while opcode exists
111 [<<+<+>>>-]<< copy to two previous fields
112 - decrease
113 [ if opcode is not plus
114 - decrease opcode
115 [ if opcode is not comma
116 - decrease opcode
117 [ if opcode is not minus
118 - decrease opcode
119 [ if opcode is not dot
120 - decrease opcode
121 [ if opcode is not left angle
122 - decrease opcode
123 [ if opcode is not right angle
124 - decrease opcode
125 [ if opcode is not left bracket
126 >>>[>]>+++++ indicate 5 bytes should be added
127 <<[<]-<< set indicator to minus one
128 -
129 ] end if (opcode is not left bracket)
130 >>[<-<->>+]<[>-<+]<+ copy indicator and increase
131 [ else (opcode is left bracket)
132 >>>[>]>++++++++ indicate 8 bytes should be added
133 <<[<]-<< set indicator to minus one
134 -
135 ] end else (opcode is left bracket)
136 ] end if (opcode is not right angle)
137 >>[<-<->>+]<[>-<+]<+ copy indicator and increase
138 [ else (opcode is right angle)
139 >>>[>]>+ indicate 1 byte should be added
140 <<[<]-<< set indicator to minus 1
141 -
142 ] end else (opcode is right angle)
143 ] end if (opcode is not left angle)
144 >>[<-<->>+]<[>-<+]<+ copy indicator and increase
145 [ else (opcode is left angle)
146 >>>[>]>+ indicate 1 byte should be added
147 <<[<]-<< set indicator to minus 1
148 -
149 ] end else (opcode is left angle)
150 ] end if (opcode is not dot)
151 >>[<-<->>+]<[>-<+]<+ copy indicator and increase
152 [ else (opcode is dot)
153 >>>[>]>++++++ indicate 6 bytes should be added
154 <<[<]-<< set indicator to minus 1
155 -
156 ] end else (opcode is dot)
157 ] end if (opcode is not minus)
158 >>[<-<->>+]<[>-<+]<+ copy indicator and increase
159 [ else (opcode is minus)
160 >>>[>]>++ indicate 2 bytes should be added
161 <<[<]-<< set indicator to minus 1
162 -
163 ] end else (opcode is minus)
164 ] end if (opcode is not comma)
165 >>[<-<->>+]<[>-<+]<+ copy indicator and increase
166 [ else (opcode is comma)
167 >>>[>]>++++++ indicate 6 bytes should be added
168 <<[<]-<< set indicator to minus 1
169 -
170 ] end else (opcode is comma)
171 ] end if (opcode is not plus)
172 >>[<-<->>+]<[>-<+]<+ copy indicator and increase
173 [ else (opcode is plus)
174 >>>[>]>++ indicate 2 bytes should be added
175 <<[<]-<< set indicator to minus 1
176 -
177 ] end else (opcode is plus)
178
179 >>+>[>]> move to increment
180 [>+ increase byte 1
181 [>>>>+>+<<<<<-]>>>>>[<<<<<+>>>>>-] copy byte 1
182 <[>-<[-]] if no overflow set field to minus 1
183 >+[- if overflow
184 <<<<+ increase byte 2
185 [>>>+>+<<<<-]>>>>[<<<<+>>>>-] copy byte 2
186 <[>-<[-]] if no overflow set field to minus 1
187 >+[- if overflow
188 <<<+ increase byte 3
189 [>>+>+<<<-]>>>[<<<+>>>-] copy byte 3
190 <[>-<[-]] if no overflow set field to minus 1
191 >+[- if overflow
192 <<+ increase byte 4
193 >>
194 ] end if
195 ] end if
196 ] end if
197 <<<<<<- decrease increment
198 ]
199
200 <<[<]> move to next opcode
201]
202
203>>>>>> move behind file size
204
205>++++++++[<++++++++++++++++>-]<-. output ELF magic bytes
206>+++++++[<-------->-]<--.
207+++++++.------.
208
209[-]+...-.........++.--.+++.---.+.-... print rest of ELF header
210>++++++++[<++++++++++>-]<++++.
211>++++++[<+++++++>-]<++.[-]++++.++++.
212>++++++[<+++++++>-]<++.[-]...........
213>+++++++[<+++++++>-]<+++.>.++++
214[<----->-]<.>.+.-.<++++++++.[-].....
215+.-........>
216++++++++[<++++++++++++++++>-]<.>++++.
217++++.>.<<.>----.++++.
218<<<<<.>.>.>. this is file size
219
220Copy the file size since we need it to initialize ecx
221>[-]>[-]<< clear the fields
222<<<[>>>>+>+<<<<<-]>>>>>[<<<<<+>>>>>-] copy the bytes
223<<<<[>>>>+>+<<<<<-]>>>>>[<<<<<+>>>>>-]
224<<<<[>>>>+>+<<<<<-]>>>>>[<<<<<+>>>>>-]
225<<<<[>>>>+>+<<<<<-]>>>>>[<<<<<+>>>>>-]
226
227We have to add 30 000 = 0x75 30 to the file size
228Start with 0x30
229
230>>>++++++[<++++++++>-]< set to 0x30
231[ while increment is not 0
232 <<<<<<+ increase byte 1
233 [>>>>+>+<<<<<-]>>>>>[<<<<<+>>>>>-] copy byte 1
234 <[>-<[-]] if no overflow set field to minus 1
235 >+[-
236 <<<<+ if overflow increase byte 2
237 [>>>+>+<<<<-]>>>>[<<<<+>>>>-] copy byte 2
238 <[>-<[-]] if no overflow set field to minus 1
239 >+[-
240 <<<+ if overflow increase byte 3
241 [>>+>+<<<-]>>>[<<<+>>>-] copy byte 3
242 <[>-<[-]] if no overflow set field to minus 1
243 >+[<<+>>-] if overflow increase byte 4
244 ]
245 ]
246 >- decrease increment
247]
248<<<<<<. print first byte
249
250Now do 0x75 00
251>>>>>>>
252+++++++[<++++++++++++++++>-]<+++++ set increment
253[ while increment is not 0
254 <<<<<+ increase byte 2
255 [>>>+>+<<<<-]>>>>[<<<<+>>>>-] copy byte 2
256 <[>-<[-]] if no overflow set field to minus 1
257 >+[-
258 <<<+ if overflow increase byte 3
259 [>>+>+<<<-]>>>[<<<+>>>-] copy byte 3
260 <[>-<[-]] if no overflow set field to minus 1
261 >+[<<+>>-] if overflow increase byte 4
262 ]
263 >- decrease increment
264]
265<<<<<.>.>. print other 3 bytes
266
267[-]<[-]<[-]<[-] clear up
268++++++.------....++++++++++++++++. print rest of header
269[-]..
270
271add 0x80 00 to file size
272>++++++++[<++++++++++++++++>-]< set counter to 0x80
273[<<<+ increase byte 2
274 [>>>>+>+<<<<<-]>>>>>[<<<<<+>>>>>-] copy byte 2
275 <[>-<[-]] if no overflow set indicator to minus 1
276 >+[- if overflow
277 <<<<+ increase byte 3
278 [>>>+>+<<<<]>>>>[<<<<+>>>>-] copy byte 3
279 <[>-<[-]] if no overflow set indicator to minus 1
280 >+[<<<+>>>-] if overflow increase byte 4
281 ]
282 <<- decrease counter
283] loop until counter is zero
284
285add 0x04 00 00 to file size
286++++ set counter to 0x04
287[<<+ increase byte 3
288 [>>>+>+<<<<-]>>>>[<<<<+>>>>-] copy byte 3
289 <[>-<[-]] if no overflow set indicator to minus 1
290 >+[<<<+>>>-] if overflow increase byte 4
291 <<- decrease counter
292] loop until counter is zero
293
294add 0x08 00 00 00 to file size
295<++++++++>
296
297Initialize registers
298>>+++++++[<+++++++>-]<. xor eax eax
299>>++++++++++++[<++++++++++++++++>-]<.
300
301<.>>+++[<+++++++++>-]<. xor ebx ebx
302
303>++++[<-------->-]<--.<<<<<<.>.>.>. mov ecx filesize
304
305>>.>>+++++[<+++++>-]<. xor edx edx
306
307>++++[<<++++>>-]<<+. inc edx
308
309Now start compiling
310
311>[-]<[-]<[-]<[-]<[-]<[-]<[-] clean up
312<<<<<<[<]> move to first instruction
313
314[ while opcode exists
315 - decrease opcode
316 [ if opcode is not plus
317 - decrease opcode
318 [ if opcode is not comma
319 - decrease opcode
320 [ if opcode is not minus
321 - decrease opcode
322 [ if opcode is not dot
323 - decrease opcode
324 [ if opcode is not left angle
325 - decrease opcode
326 [ if opcode is not right angle
327 - decrease opcode
328 [ if opcode is not left bracket
329 <++++[>------<-]>. output e9
330 [-] clear this field
331 >[>]>>>>>>>>[>>>>>>] move to end of loop size stack
332 -------->->->-<<< initialize increment
333 <<<<< move to byte 1 of size
334 [ while byte 1 is not zero
335 >>>>>- decrease byte 1
336 [>>>>+>+<<<<<-] copy byte 1
337 >>>>>[<<<<<+>>>>>-]
338 <[>-<[-]] if no underflow set field to minus 1
339 >+[- if underflow
340 <<<<- decrease byte 2
341 [>>>+>+<<<<-] copy byte 2
342 >>>>[<<<<+>>>>-]
343 <[>-<[-]] if no underflow set field to minus 1
344 >+[- if underflow
345 <<<- decrease byte 3
346 [>>+>+<<<-] copy byte 3
347 >>>[<<<+>>>-]
348 <[>-<[-]] if no underflow set field to minus 1
349 >+[-<<->>] if underflow decrease byte 4
350 ] end if
351 ] end if
352 <<<<<<<<<<- decrease byte 1 of size
353 ] end while
354 > move to byte 2 of size
355 [ while byte 2 is not zero
356 >>>>>- decrease byte 2
357 [>>>+>+<<<<-] copy byte two
358 >>>>[<<<<+>>>>-]
359 <[>-<[-]] if no underflow set field to minus 1
360 >+[- if underflow
361 <<<- decrease byte 3
362 [>>+>+<<<-] copy byte 3
363 >>>[<<<+>>>-]
364 <[>-<[-]] if no underflow set field to minus 1
365 >+[-<<->>] if underflow decrease byte 4
366 ] end if
367 <<<<<<<<<- decrease byte 2 of size
368 ] end while
369 > move to byte 3 of size
370 [ while byte 3 is not zero
371 >>>>>- decrease byte 3
372 [>>+>+<<<-] copy byte 3
373 >>>[<<<+>>>-]
374 <[>-<[-]] if no underflow set field to minus 1
375 >+[-<<->>] if underflow decrease byte 4
376 <<<<<<<<- decrease byte 3 of size
377 ]
378 > move to byte 4 of size
379 [ while byte 4 is not zero
380 >>>>>-<<<<<- decrease byte 4
381 ]
382 >->.>.>.>. print increment
383 [+]<[+]<[+]<[+] clear increment
384 <<<<<<- remove size from stack
385 <[<<<<<<]<<<<<<<<[<] move back to opcode
386 <-> set indicator to minus 1
387 ] end if (opcode is not left bracket)
388 <+ increase indicator
389 [ else (opcode is left bracket)
390 ++++++[>++++++++<-] set to 38
391 >++.---------. output 3a 31
392 <+++++++++++++++. output 0f
393 +[>+++++<-]>+++. output 84
394 [-] clear this byte
395 clear the byte counter
396 + set nesting level to one
397
398 [ while nesting greater than 0
399 >[<<<+<+>>>>-] copy opcode before nesting level
400 <<<------- subtract 7 from opcode
401 [ if opcode is not left bracket
402 - decrease opcode
403 [ if opcode is not right bracket
404 [+] clear field
405 >-< set indicator to minus 1
406 ] end if opcode is not right braket
407 >+ increase indicator
408 [ else (opcode is right bracket)
409 >-<- decrease nesting level
410 ] end else (opcode is right bracket)
411 -< set indicator to minus 1
412 ] end if (opcode is not left bracket)
413 >+ increase indicator
414 [ else (opcode is left bracket)
415 >+<- increase nesting level
416 ] end else (opcode is left bracket)
417 >[>+<-]> copy nesting to next field
418 ] end while (nesting greater than 0)
419 <<<< move to last opcode in loop
420 [ while there are opcodes
421 [>>>+>+<<<<-] copy the opcode twice
422 >>> move to first copy
423 - decrease opcode
424 [ if opcode is not plus
425 - decrease opcode
426 [ if opcode is not comma
427 - decrease opcode
428 [ if opcode is not minus
429 - decrease opcode
430 [ if opcode is not dot
431 - decrease opcode
432 [ if opcode is not left angle
433 - decrease opcode
434 [ if opcode is not right angle
435 - decrease opcode
436 [ if opcode is not left bracket
437 - then it must be right bracket
438 set increment to five bytes
439 <<+++++>->
440 ] end if (opcode is not left bracket)
441 <+ increase indicator
442 [ else (opcode is left bracket)
443 set increment to 8 bytes
444 <++++++++>-
445 ] end else (opcode is left bracket)
446 -> set indicator to minus 1
447 ] end if (opcode is not right angle)
448 <+ increase indicator
449 [ else (opcode is right angle)
450 <+>- set increment to 1 byte
451 ] end else (opcode is right angle)
452 -> set indicator to minus 1
453 ] end if (opcode is not left angle)
454 <+ increase indicator
455 [ else (opcode is left angle)
456 <+>- set increment to 1 byte
457 ] end else (opcode is left angle)
458 -> set indicator to minus 1
459 ] end else (opcode is not dot)
460 <+ increase indicator
461 [ else (opcode is dot)
462 <++++++>- set increment to 6 bytes
463 ] end else (opcode is dot)
464 -> set indicator to minus 1
465 ] end if (opcode is not minus)
466 <+ increase indicator
467 [ else (opcode is minus)
468 <++>- set increment to two bytes
469 ] end else (opcode is minus)
470 -> set indicator to minus 1
471 ] end if (opcode is not comma)
472 <+ increase indicator
473 [ else (opcode is comma)
474 <++++++>- set increment to 6 bytes
475 ] end else (opcode is comma)
476 -> set indicator to minus 1
477 ] end if (opcode is not plus)
478 <+ increase indicator
479 [ else (opcode is plus)
480 <++>- set increment to 2 bytes
481 ] end else (opcode is plus)
482 <[>>>[>]>+<<[<]<<-] copy increment behind program
483 >>>[>]> move to increment
484 [ while increment is not zero
485 >+ increase byte 1
486 [>>>>+>+<<<<<-] copy byte 1
487 >>>>>[<<<<<+>>>>>-]
488 <[>-<[-]] if no overflow set field to minus 1
489 >+[- if overflow
490 <<<<+ increase byte 2
491 [>>>+>+<<<<-] copy byte 2
492 >>>>[<<<<+>>>>-]
493 <[>-<[-]] if no overflow set field to minus 1
494 >+[- if overflow
495 <<<+ increase byte 3
496 [>>+>+<<<-] copy byte 3
497 >>>[<<<+>>>-]
498 <[>-<[-]] if no overflow set field to minus 1
499 >+[- if overflow
500 <<+>> increase byte 4
501 ]
502 ] end if
503 ] end if
504 <<<<<<- decrease increment
505 ] end while
506 <<[<]<<<< move to next opcode
507 ] end while opcode exists
508 >>>>>[>]>>.>.>.>. output the loop increment
509 <<< move to byte 1
510 copy byte 1 on stack
511 [>>>>>>[>>>>>>]>+<<[<<<<<<]<<<<<-]
512 > move to byte 2
513 copy byte 2 on stack
514 [>>>>>[>>>>>>]>>+<<<[<<<<<<]<<<<-]
515 > move to byte 3
516 copy byte 3 on stack
517 [>>>>[>>>>>>]>>>+<<<<[<<<<<<]<<<-]
518 > move to byte 4
519 copy byte 4 on stack
520 [>>>[>>>>>>]>>>>+<<<<<[<<<<<<]<<-]
521 set surrounding 1 bytes
522 >>>[>>>>>>]+>>>>>+<<<<<<[<<<<<<]<<
523 <<<<<<[<] move back to start of loop
524 < move to indicator field
525 ] end else (opcode is left bracket)
526 -> set indicator to minus 1
527 ] end if (opcode is not right angle)
528 <+ increase indicator
529 [ else (opcode is right angle)
530 +++++++[>++++++++<-]>+ set to 41
531 .[-]< output 41 and clear up
532 ] end else (opcode is right angle)
533 -> set indicator to minus 1
534 ] end if (opcode is not left angle)
535 <+ increase indicator
536 [ else (opcode is left angle)
537 +++++++[>+++++++++<-]>+. output 49
538 [-]< clear up
539 ] end else (opcode is left angle)
540 -> set indicator to minus 1
541 ] end if (opcode is not dot)
542 <+ increase indicator
543 [ else (opcode is dot)
544 ++++++++++ set to b0
545 [>++++++++++++++++<-]>. output b0
546 <++++.>+++.<---. output 04 b3 01
547 +[>+++++++++++++<-]>. output cd
548 <+++++++[>-----------<-]>. output 80
549 [-]< clear up
550 ] end else (opcode is dot)
551 -> set indicator to minus 1
552 ] end if (opcode is not minus)
553 <+ increase indicator
554 [ else (opcode is minus)
555 >--.++<++++++++.--------- output fe 09
556 ] end else (opcode is minus)
557 -> set indicator to minus 1
558 ] end if (opcode is not comma)
559 <+ increase indicator
560 [ else (opcode is comma)
561 ++++++++++[>++++++++++++++++<-] set to b0
562 >.<+++.>+++.<---. output b0 03 b3 00
563 ++[>+++++++++++++<-]>.< output cd
564 +++++++[>-----------<-]>. output 80
565 [-]< clear up
566 ] end else (opcode is comma)
567 -> set indicator to minus one
568 ] end if (opcode is not plus)
569 <+ increase indicator
570 [ else (opcode is plus)
571 ---.+++.- output fe 01
572 ] end else (opcode is plus)
573 >> move to next opcode
574]
575
576[>]>
577
578Clean up
579
580>+++++++++++[<++++++++++++++++>-]<. mov al 1
581>+.
582
583<+++.>-. mov bl 0
584
585++++[<++++++>-]<++. int 0x80
586>>++++++++[<++++++++++++++++>-]<.
Note: See TracBrowser for help on using the repository browser.