FB Quine

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
Juiced
Posts: 31
Joined: Apr 04, 2011 20:32

FB Quine

Post by Juiced »

Code: Select all

dim as integer i
dim as string q=chr(34),c(2)={chr(44)+chr(95),chr(125)},Array(11)={_
"dim as integer i",_
"dim as string q=chr(34),c(2)={chr(44)+chr(95),chr(125)},Array(11)={_",_
"for i=0 to 1",_
"    print Array(i)",_
"next i",_
"for i=0 to 10",_
"   print q+Array(i)+q+c(iif(i=10,1,0))",_
"next i",_
"for i=2 to 10",_
"   print Array(i)",_
"next i"}
for i=0 to 1
    print Array(i)
next i
for i=0 to 10
    print q+Array(i)+q+c(iif(i=10,1,0))
next i
for i=2 to 10
    print Array(i)
next i
Writing a quine is an excellent exercise for anyone looking for a good programming challenge. If you don't know what a quine is: http://en.wikipedia.org/wiki/Quine_(computing)
TJF
Posts: 3809
Joined: Dec 06, 2009 22:27
Location: N47°, E15°
Contact:

Re: FB Quine

Post by TJF »

Save as 'Quine.bas', compile and run

Code: Select all

DIM code AS ZSTRING PTR
DIM code_len AS UINTEGER
ASM .section .data
ASM .LT_START_OF_FILE_code:
ASM __code__start = .
ASM .incbin "Quine.bas"
ASM __code__len = . - __code__start
ASM .section .text
ASM mov dword PTR [code], offset .LT_START_OF_FILE_code
ASM mov dword PTR [code_len], offset __code__len
?LEFT(*code, code_len)
BTW: it still works if you edit the source code (ie add some comments).
VANYA
Posts: 1866
Joined: Oct 24, 2010 15:16
Location: Ярославль
Contact:

Re: FB Quine

Post by VANYA »

TJF! Where you can read about the built-in assembler?

That is very familiar to me a little assembler. But I do not understand is this:

Code: Select all

ASM __code__len = . - __code__start
TJF
Posts: 3809
Joined: Dec 06, 2009 22:27
Location: N47°, E15°
Contact:

Re: FB Quine

Post by TJF »

VANYA wrote:TJF! Where you can read about the built-in assembler?

That is very familiar to me a little assembler. But I do not understand is this:

Code: Select all

ASM __code__len = . - __code__start
I'm no ASM expert. Most of my knowledge I got from a script from Prof. Wüst, Fachhochschule Gießen-Friedberg (sorry, I've no link). You may follow the links on the wikipedia sites.

This line calculates the length of the file (= STRING). The '.' is the current pointer, '__code__start' is the pointer before the 'incbin' statement and the difference is the length.
VANYA
Posts: 1866
Joined: Oct 24, 2010 15:16
Location: Ярославль
Contact:

Re: FB Quine

Post by VANYA »

I am interested in not the assembly instructions, but these records:
LT_START_OF_FILE_code
TJF
Posts: 3809
Joined: Dec 06, 2009 22:27
Location: N47°, E15°
Contact:

Re: FB Quine

Post by TJF »

'.LT_START_OF_FILE_code' is just a label.
VANYA
Posts: 1866
Joined: Oct 24, 2010 15:16
Location: Ярославль
Contact:

Re: FB Quine

Post by VANYA »

TJF wrote:'.LT_START_OF_FILE_code' is just a label.
Thanks friend!
TJF
Posts: 3809
Joined: Dec 06, 2009 22:27
Location: N47°, E15°
Contact:

Re: FB Quine

Post by TJF »

You're welcome.

BTW:

the label is not realy necessary

Code: Select all

DIM AS ZSTRING PTR code
DIM AS UINTEGER code_len
ASM .section .data
ASM __code__start = .
ASM .incbin "Quine.bas"
ASM __code__len = . - __code__start
ASM .section .text
ASM mov dword PTR [code], offset __code__start
ASM mov dword PTR [code_len], offset __code__len
?LEFT(*code, code_len)
codeFoil
Posts: 256
Joined: Dec 22, 2011 4:45
Location: United States
Contact:

Re: FB Quine

Post by codeFoil »

VANYA wrote:I am interested in not the assembly instructions, but these records:
LT_START_OF_FILE_code
http://sourceware.org/binutils/docs/as/
Most of the inline assembly code is foisted upon the gnu assembler.
VANYA
Posts: 1866
Joined: Oct 24, 2010 15:16
Location: Ярославль
Contact:

Re: FB Quine

Post by VANYA »

codeFoil wrote:
VANYA wrote:I am interested in not the assembly instructions, but these records:
LT_START_OF_FILE_code
http://sourceware.org/binutils/docs/as/
Most of the inline assembly code is foisted upon the gnu assembler.
Thanks.
Juiced
Posts: 31
Joined: Apr 04, 2011 20:32

Re: FB Quine

Post by Juiced »

TJF wrote:Save as 'Quine.bas', compile and run

Code: Select all

DIM code AS ZSTRING PTR
DIM code_len AS UINTEGER
ASM .section .data
ASM .LT_START_OF_FILE_code:
ASM __code__start = .
ASM .incbin "Quine.bas"
ASM __code__len = . - __code__start
ASM .section .text
ASM mov dword PTR [code], offset .LT_START_OF_FILE_code
ASM mov dword PTR [code_len], offset __code__len
?LEFT(*code, code_len)
BTW: it still works if you edit the source code (ie add some comments).
Even though I don't know assembly, from looking at this and guessing, it looks like you're extracting the source from memory. I find these types of quines less interesting because the source isn't being copied from within it's own source code. These are considered cheats, like this Basic version:
10 LIST
TJF
Posts: 3809
Joined: Dec 06, 2009 22:27
Location: N47°, E15°
Contact:

Re: FB Quine

Post by TJF »

Juiced wrote:
TJF wrote:Even though I don't know assembly, from looking at this and guessing, it looks like you're extracting the source from memory. I find these types of quines less interesting because the source isn't being copied from within it's own source code. These are considered cheats, like this Basic version:
10 LIST
The version
  • 10 LIST
only works in interpreters that support the LIST statement -- not in a compiler like FB.

But you're right, my solution is a fake. It reads the source code file in to the data section of the binary and prints it on run-time. Sorry, IMHO writing code that reproduces itself makes not realy sense ; )
gothon
Posts: 225
Joined: Apr 11, 2011 22:22

Re: FB Quine

Post by gothon »

Preprocessor stringize is still allowed though, isn't it?

Code: Select all

#Define P(X) Print X: Print "P(" & #X & ")"
P("#Define P(X) Print X: Print ""P("" & #X & "")""")
Edit: Compacted 64-65 byte Version:

Code: Select all

#Define P(X)?X:?"P("&#X&")"
P("#Define P(X)?X:?""P(""&#X&"")""")
Juiced
Posts: 31
Joined: Apr 04, 2011 20:32

Re: FB Quine

Post by Juiced »

gothon wrote:Preprocessor stringize is still allowed though, isn't it?

Code: Select all

#Define P(X) Print X: Print "P(" & #X & ")"
P("#Define P(X) Print X: Print ""P("" & #X & "")""")
Edit: Compacted 64-65 byte Version:

Code: Select all

#Define P(X)?X:?"P("&#X&")"
P("#Define P(X)?X:?""P(""&#X&"")""")
Nice, very elegant!
counting_pine
Site Admin
Posts: 6323
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Re: FB Quine

Post by counting_pine »

I managed to lose another byte*2 before the #X using implicit string literal concatenation:

Code: Select all

#Define P(X)?X:?"P("#X ")"
P("#Define P(X)?X:?""P(""#X "")""")
Note: A space (or ampersand) is necessary after #X otherwise the following quote gets sucked into the string literal of #X, as seen here:

Code: Select all

#define p(x) print "abc"#x"ghi"
p(def) ''expanded to: print "abc"$"def""ghi"
That probably shouldn't happen..?
Post Reply