Could you please post the source code instead of the binary? Some of us don't have a Prop (or a serial-enabled version of SpinSim) within arm's reach to run the binary. I'm too lazy to get up from my chair to get my prop board that's sitting on a shelf 6 feet away.
Would not it be most challenging to use a decompiler (for high level languages) or disassembler (for assembly) that is sufficient to produce the original source of the author and include enough formatting information, symbol names and locations, and comments as data that is used in the decompilation of the app? Would not this meet the challenge of reproducing the authors original source? For (based on the understanding of a Quine as a challenge) what chalenge is there in simply outputting the source from data and then reproducing the data behind that?
I can not give my example at this time, as my only 2 Propellers are in continuous use for another test at this time. Thus I am unable to reliably test my code (I have not verified the accuracy of my PASM simulator, nor have I tested out a simulator by any one else, to know the differences from the real Propeller).
...what chalenge is there in simply outputting the source from data and then reproducing the data behind that?
The challenge, as I see it, is to devise the shortest program that can do that. But, according to this page on quines, they call what you describe a "cheat". I do notice from their examples, however, that facilities like print or printf are treated as an atomic element of many languages, which makes the job much easier.
A program may well be able to decompile itself. Perhaps not quite into the source as originally written. Generally there is no way it recreate the formatting or comments. That information is lost during compilation.
Heater:
As I stated above the decompiler should be written to use identifiers, comments, and formatting information from the data section of the program, and it would be a purpose specific decompiler, not general purpose.
Phil:
Beings that the authors original source would be reproduced, and all information used to due so is contained in the program; How is this a cheat?
Phil:
Further the page to witch you link gives examples of interpreted languages, in witch the source and the program are one and the same, using a command of the language with the same meaning as LIST in BASIC. While they say these are not cheats they say that doing so in BASIC is a cheat. So where is the standard? Would a basic program that peeks in memory from where it is being executed and then outputs this be a cheat? After all this is what the BASIC LIST command does (at least with most basic interpreters.
David Saunders,
OK I'll buy that decompiler idea.
Looking at some of those examples some of them seem to be feindishly short. Perhaps there is room for improvement in Spin.
10 DATA "B$='DATA '+CHR$(34)
20 DATA "FOR J=10 TO 180 STEP 10
30 DATA "READ A$
40 DATA PRINT J;B$;A$
50 DATA "IF J<>90 THEN 170
60 DATA "RESTORE
70 DATA "B$=' ' 80 DATA "NEXT J
90 DATA "END
100 B$='DATA '+CHR$(34)
110 FOR J=10 TO 180 STEP 10
120 READ A$
130 PRINT J;B$;A$
140 IF J<>90 THEN 170
150 RESTORE
160 B$=' '
170 NEXT J
180 END
This one is interesting to me.
a$[1]="a$[":a$[2]="]=":a$[3]="q$=chr$(34):for i=1 to 3:?a$[1]str$(i)a $[2]q$ a$q$ chr$(58);:next i:?a$[3]":q$=chr$(34):for i=1 to 3:?a$[ 1]str$(i)a$[2]q$ a$q$ chr$(58);:next i:?a$[3]
IMHO, including things like "list" uses a reference outside the program to complete the task. I think that's the standard; namely, limiting references to those entities in the program to the highest degree possible. A secondary standard would be the number of references used, where less is more. Finally, "clever", or "off label" uses of the language elements is "interesting", for bonus points.
Looking the examples over, I see two basic themes. One is where the program contains the data needed to output the program, and that data really is data.
The other is where the program really is the data, both executed and used as data, where the nature of the program is sufficient to output the program, without using something like "list".
IMHO, including things like "list" uses a reference outside the program to complete the task. I think that's the standard; namely, limiting references to those entities in the program to the highest degree possible. A secondary standard would be the number of references used, where less is more. Finally, "clever", or "off label" uses of the language elements is "interesting", for bonus points.
I don't think it's invalid. Seems to work just the same way the one in BASIC above does, where the program listing is in DATA statements. It's just not a very interesting one, because there is data, and there is the program. The program acts on the data to output itself.
The more interesting ones are where the data and the program are one and the same, with no discrete block of data that's easy to process.
And that's subjective, IMHO.
So is something like "list". Technically, "list" is part of the language, so I would call it valid, but not interesting. A BASIC program that uses peek and poke to read itself, parse, and output itself is far more interesting, because it is far more challenging. Frankly, the number of self-references is another point of interest. The "list" one does not require many, because "list" does most of the work. The program that interprets itself requires far more self-references. That's "interesting", IMHO.
BTW: A tangent that's probably gonna make a mess is the Propeller COG vs many other CPU's. I find Propeller PASM interesting because every long in the memory space is either program or data. The distinction is up to the programmer. A storage location is just a storage location, and each one is atomic, containing a value that is either instruction or data.
On many other CPUs, the distinction between program and data is not as pure. A storage location may contain part of a instruction, for example.
The interesting quines to me, and make no mistake I'm new to these just reading with interest, are those that are "pure" like that, where the data and the program are combined to appear as just a program, not a program that acts on a well defined unit of data.
Author: Bertram Felgenhauer
Notes: 80x86 TASM. Basically, the program reads it's own code/data segment and converts itto decimal numbers, seperated by "\nDB ".
MODEL TINY
.CODE
.STARTUP
DB 177
DB 076
DB 186
DB 044
DB 001
DB 172
DB 180
DB 036
DB 179
DB 004
DB 191
DB 080
DB 001
DB 079
DB 136
DB 037
DB 212
DB 010
DB 004
DB 048
DB 134
DB 196
DB 075
DB 117
DB 244
DB 180
DB 009
DB 205
DB 033
DB 178
DB 071
DB 226
DB 228
DB 178
DB 038
DB 205
DB 033
DB 195
DB 013
DB 010
DB 069
DB 078
DB 068
DB 036
DB 077
DB 079
DB 068
DB 069
DB 076
DB 032
DB 084
DB 073
DB 078
DB 089
DB 013
DB 010
DB 046
DB 067
DB 079
DB 068
DB 069
DB 013
DB 010
DB 046
DB 083
DB 084
DB 065
DB 082
DB 084
DB 085
DB 080
DB 013
DB 010
DB 068
DB 066
DB 032END
Beautiful! (if it does, in fact output that exact text)
It is beautiful because it references itself in every way, except for the output function. The only way to get a more self-referencing thing would be to code it for a specific machine, where the output can be displayed, or something with only the code input.
That's not portable, and because of that, not a significant consideration. STDOUT, printf, etc... are simply necessary things, but for a seriously pure and academic example, IMHO.
LIST is not a necessary thing, and perhaps that's where the line is on "cheats", and I think I'm just going to factor all that out, and say that if it outputs itself, it's a quine, with there being only interesting quines, and not so interesting ones, with interesting being keyed to the references that exist outside the input, and whether or not the program parses itself, rather than just outputting a formatted copy of itself.
Both of those increase difficulty, which makes them interesting.
Ok I see the point of the beauty, I agree that more complex and shorter solutions are much much more interesting.
My quine for the prop (witch I shall post once I have a free Propeller on witch to test it) uses a very similar method to the x86 asm one mentioned above. Of course it uses LONG instead of DB and has to reproduce the SPIN loader code (as it is meant to run by it self on a propeller). As such I am trying to assure my self that this is a valid quine, especially as other self referrals are often considered invalid, even when they do not rely on an external file in any way shape or form.
I should note that I wrote it before seeing the above code, it is just the most sensible method for doing such a thing in a pure way.
Yeah, I think it's valid. And the SPIN portion increases the overall difficulty. The pure assembly example above is not as difficult as one on the Prop will be, because the listing is less uniform, which presents a challenge in terms of overall size.
The nature of the machine has to be considered.
Edit: I just noticed you did cite the LAST example. I had looked at some of the earlier ones. Sorry, if that came across goofy.
Here's a Spin quine that generates it's source by looking at it's bytecodes. The first file is the actual quine and the second file is the one that generated it. They are functionally equivalent, but the quine doesn't contain comments or meaningful variable names.
Yes, genquine.spin is not a quine, but it's output is a valid quine. quine.spin will produce an identical copy of itself.
It took quite a few lines of code to generate Spin source from bytecodes. I had to limit the number of operators I used, and I use "repeat while" to do all my loops and if statements.
Comments
Produces more readable PASM code
Thanks,
Dave
I can not give my example at this time, as my only 2 Propellers are in continuous use for another test at this time. Thus I am unable to reliably test my code (I have not verified the accuracy of my PASM simulator, nor have I tested out a simulator by any one else, to know the differences from the real Propeller).
-Phil
As I stated above the decompiler should be written to use identifiers, comments, and formatting information from the data section of the program, and it would be a purpose specific decompiler, not general purpose.
Phil:
Beings that the authors original source would be reproduced, and all information used to due so is contained in the program; How is this a cheat?
Further the page to witch you link gives examples of interpreted languages, in witch the source and the program are one and the same, using a command of the language with the same meaning as LIST in BASIC. While they say these are not cheats they say that doing so in BASIC is a cheat. So where is the standard? Would a basic program that peeks in memory from where it is being executed and then outputs this be a cheat? After all this is what the BASIC LIST command does (at least with most basic interpreters.
OK I'll buy that decompiler idea.
Looking at some of those examples some of them seem to be feindishly short. Perhaps there is room for improvement in Spin.
10 LIST : REM MER : TSIL 01
This was not:
10 READ A$:PRINT 10 A$:PRINT 20 "DATA" A$ 20 DATA READ A$:PRINT 10 A$:PRINT 20 "DATA" A$
Neither was this:10 DATA "B$='DATA '+CHR$(34)
20 DATA "FOR J=10 TO 180 STEP 10
30 DATA "READ A$
40 DATA PRINT J;B$;A$
50 DATA "IF J<>90 THEN 170
60 DATA "RESTORE
70 DATA "B$=' ' 80 DATA "NEXT J
90 DATA "END
100 B$='DATA '+CHR$(34)
110 FOR J=10 TO 180 STEP 10
120 READ A$
130 PRINT J;B$;A$
140 IF J<>90 THEN 170
150 RESTORE
160 B$=' '
170 NEXT J
180 END
This one is interesting to me.
a$[1]="a$[":a$[2]="]=":a$[3]="q$=chr$(34):for i=1 to 3:?a$[1]str$(i)a $[2]q$ a$q$ chr$(58);:next i:?a$[3]":q$=chr$(34):for i=1 to 3:?a$[ 1]str$(i)a$[2]q$ a$q$ chr$(58);:next i:?a$[3]
IMHO, including things like "list" uses a reference outside the program to complete the task. I think that's the standard; namely, limiting references to those entities in the program to the highest degree possible. A secondary standard would be the number of references used, where less is more. Finally, "clever", or "off label" uses of the language elements is "interesting", for bonus points.
Looking the examples over, I see two basic themes. One is where the program contains the data needed to output the program, and that data really is data.
The other is where the program really is the data, both executed and used as data, where the nature of the program is sufficient to output the program, without using something like "list".
The more interesting ones are where the data and the program are one and the same, with no discrete block of data that's easy to process.
And that's subjective, IMHO.
So is something like "list". Technically, "list" is part of the language, so I would call it valid, but not interesting. A BASIC program that uses peek and poke to read itself, parse, and output itself is far more interesting, because it is far more challenging. Frankly, the number of self-references is another point of interest. The "list" one does not require many, because "list" does most of the work. The program that interprets itself requires far more self-references. That's "interesting", IMHO.
BTW: A tangent that's probably gonna make a mess is the Propeller COG vs many other CPU's. I find Propeller PASM interesting because every long in the memory space is either program or data. The distinction is up to the programmer. A storage location is just a storage location, and each one is atomic, containing a value that is either instruction or data.
On many other CPUs, the distinction between program and data is not as pure. A storage location may contain part of a instruction, for example.
The interesting quines to me, and make no mistake I'm new to these just reading with interest, are those that are "pure" like that, where the data and the program are combined to appear as just a program, not a program that acts on a well defined unit of data.
Author: Bertram Felgenhauer Notes: 80x86 TASM. Basically, the program reads it's own code/data segment and converts it to decimal numbers, seperated by "\nDB ". MODEL TINY .CODE .STARTUP DB 177 DB 076 DB 186 DB 044 DB 001 DB 172 DB 180 DB 036 DB 179 DB 004 DB 191 DB 080 DB 001 DB 079 DB 136 DB 037 DB 212 DB 010 DB 004 DB 048 DB 134 DB 196 DB 075 DB 117 DB 244 DB 180 DB 009 DB 205 DB 033 DB 178 DB 071 DB 226 DB 228 DB 178 DB 038 DB 205 DB 033 DB 195 DB 013 DB 010 DB 069 DB 078 DB 068 DB 036 DB 077 DB 079 DB 068 DB 069 DB 076 DB 032 DB 084 DB 073 DB 078 DB 089 DB 013 DB 010 DB 046 DB 067 DB 079 DB 068 DB 069 DB 013 DB 010 DB 046 DB 083 DB 084 DB 065 DB 082 DB 084 DB 085 DB 080 DB 013 DB 010 DB 068 DB 066 DB 032 END
Beautiful! (if it does, in fact output that exact text)It is beautiful because it references itself in every way, except for the output function. The only way to get a more self-referencing thing would be to code it for a specific machine, where the output can be displayed, or something with only the code input.
That's not portable, and because of that, not a significant consideration. STDOUT, printf, etc... are simply necessary things, but for a seriously pure and academic example, IMHO.
LIST is not a necessary thing, and perhaps that's where the line is on "cheats", and I think I'm just going to factor all that out, and say that if it outputs itself, it's a quine, with there being only interesting quines, and not so interesting ones, with interesting being keyed to the references that exist outside the input, and whether or not the program parses itself, rather than just outputting a formatted copy of itself.
Both of those increase difficulty, which makes them interesting.
My quine for the prop (witch I shall post once I have a free Propeller on witch to test it) uses a very similar method to the x86 asm one mentioned above. Of course it uses LONG instead of DB and has to reproduce the SPIN loader code (as it is meant to run by it self on a propeller). As such I am trying to assure my self that this is a valid quine, especially as other self referrals are often considered invalid, even when they do not rely on an external file in any way shape or form.
I should note that I wrote it before seeing the above code, it is just the most sensible method for doing such a thing in a pure way.
The nature of the machine has to be considered.
Edit: I just noticed you did cite the LAST example. I had looked at some of the earlier ones. Sorry, if that came across goofy.
CON _CLKMODE=XTAL1+PLL16X,_XINFREQ=5000000 PUB m coginit(0, @b,@b) DAT b MOV DIRA, pinmask wr MOV OUTA, pinmask wr MOV pc, #b wr MOV opcode_addr, PAR wr SHL conditions_addr, #$002 wr ADD conditions_addr, PAR wr SHL operations_addr, #$002 wr ADD operations_addr, PAR wr SHL flags_str_addr, #$002 wr ADD flags_str_addr, PAR wr SHL long_str_addr, #$002 wr ADD long_str_addr, PAR wr SHL byte_str_addr, #$002 wr ADD byte_str_addr, PAR wr SHL registers_addr, #$002 wr ADD registers_addr, PAR wr MOV str_address, #prologue wr SHL str_address, #$002 wr ADD str_address, PAR wr JMPRET idx_str_ret, #str wr mainl RDLONG code_end, opcode_addr ADD opcode_addr, #$004 wr MOV src, code_end wr AND src, #$1FF wr SHR code_end, #$009 wr MOV dst, code_end wr AND dst, #$1FF wr SHR code_end, #$009 wr MOV cond, code_end wr AND cond, #$00F wr SHR code_end, #$004 wr MOV imm, code_end wr AND imm, #$001 wr SHR code_end, #$001 wr MOV flags, code_end wr AND flags, #$007 wr SHR code_end, #$003 wr MOV tmp, pc wr JMPRET find_label_ret, #find_label wr AND str_address, str_address nr, wz if_z JMPRET b, #no_label nr JMPRET idx_str_ret, #str wr MOV char, #$00A wr JMPRET tx_ret, #tx wr no_label MOV tmp, #$004 wr JMPRET align_ret, #align wr MOV tmp, cond wr MOV str_address, conditions_addr wr JMPRET idx_str_ret, #idx_str wr MOV tmp, #$012 wr JMPRET align_ret, #align wr SUB cond, #b nr, wz if_z MOV tmp, #b wr if_z MOV flags, #$008 wr if_z JMPRET b, #non_mem nr MOV tmp, code_end wr ADD tmp, #$001 wr SUB tmp, #$004 nr, wz, wc if_nc ADD tmp, #$003 wr if_nc JMPRET b, #non_mem nr AND flags, #$001 nr, wc if_c ADD tmp, #$003 wr SHR flags, #$001 wr ADD flags, #$008 wr non_mem MOV str_address, operations_addr wr JMPRET idx_str_ret, #idx_str wr SUB cond, #b nr, wz if_z JMPRET b, #no_oprnds nr MOV tmp, #$01A wr JMPRET align_ret, #align wr MOV tmp, dst wr JMPRET label_or_binary_ret, #label_or_binary wr MOV char, #no_label wr JMPRET tx_ret, #tx wr MOV char, #$020 wr JMPRET tx_ret, #tx wr MOV tmp, #$031 wr JMPRET align_ret, #align wr AND imm, #$001 nr, wz if_nz MOV char, #$023 wr if_nz JMPRET tx_ret, #tx wr MOV tmp, src wr JMPRET label_or_binary_ret, #label_or_binary_dst wr no_oprnds MOV tmp, #$048 wr JMPRET align_ret, #align wr MOV char, #$020 wr JMPRET tx_ret, #tx wr MOV str_address, flags_str_addr wr MOV tmp, flags wr JMPRET idx_str_ret, #idx_str wr MOV char, #$00A wr JMPRET tx_ret, #tx wr ADD pc, #$001 wr DJNZ code_size, #mainl wr MOV char, #$00A wr JMPRET tx_ret, #tx wr MOV char, #$00A wr JMPRET tx_ret, #tx wr vars_loop MOV tmp, pc wr JMPRET find_label_ret, #find_label wr SUB str_address, #b nr, wz if_z JMPRET b, #no_var_label nr JMPRET idx_str_ret, #str wr MOV char, #$00A wr JMPRET tx_ret, #tx wr no_var_label MOV str_address, long_str_addr wr JMPRET idx_str_ret, #str wr RDLONG tmp, opcode_addr ADD opcode_addr, #$004 wr MOV tmp_ctr, #$008 wr ROR tmp, #$01C wr JMPRET binary2_ret, #binary2 wr MOV char, #$00A wr JMPRET tx_ret, #tx wr ADD pc, #$001 wr DJNZ vars_size, #vars_loop wr MOV tmp, pc wr JMPRET find_label_ret, #find_label wr SUB str_address, #b nr, wz if_z JMPRET b, #print_data nr JMPRET idx_str_ret, #str wr MOV char, #$00A wr JMPRET tx_ret, #tx wr print_data SHL data_size, #$002 wr MOV code_end, #b wr data_loop SUB code_end, #b nr, wz if_nz JMPRET b, #comma nr MOV str_address, byte_str_addr wr JMPRET idx_str_ret, #str wr JMPRET b, #bits nr comma MOV char, #no_label wr JMPRET tx_ret, #tx wr bits MOV tmp_ctr, #$008 wr RDBYTE tmp, opcode_addr ADD opcode_addr, #$001 wr SUB tmp, #$020 nr, wz, wc if_c JMPRET b, #bin nr SUB tmp, #$07F nr, wz, wc if_nc_and_nz JMPRET b, #bin nr MOV char, #$022 wr JMPRET tx_ret, #tx wr MOV char, tmp wr JMPRET tx_ret, #tx wr MOV char, #$022 wr JMPRET tx_ret, #tx wr JMPRET b, #nxt nr bin JMPRET binary2_ret, #binary wr nxt SUB code_end, #$00F nr, wz if_z MOV char, #$00A wr if_z JMPRET tx_ret, #tx wr ADD code_end, #$001 wr AND code_end, #$00F wr DJNZ data_size, #data_loop wr HUBOP code_size, #$001 wr HUBOP code_size, #$003 nr str MOV tmp, #b wr idx_str TJZ tmp, #done nr seek_loop RDBYTE char, str_address wz ADD str_address, #$001 wr if_nz JMPRET b, #seek_loop nr DJNZ tmp, #seek_loop wr done RDBYTE char, str_address wz if_z JMPRET b, #idx_str_ret nr ADD str_address, #$001 wr JMPRET tx_ret, #tx wr JMPRET b, #done nr idx_str_ret JMPRET b, #b nr label_or_binary_dst AND imm, imm nr, wz if_nz JMPRET b, #noreg nr label_or_binary SUB tmp, #$1F0 nr, wz, wc if_c JMPRET b, #noreg nr SUB tmp, #$1FF nr, wz, wc MOV str_address, registers_addr wr SUB tmp, #$1F0 wr JMPRET idx_str_ret, #idx_str wr JMPRET b, #label_or_binary_ret nr if_nc_and_nz JMPRET b, #noreg nr noreg JMPRET find_label_ret, #find_label wr SUB str_address, #b nr, wz if_z JMPRET b, #out_binary nr JMPRET idx_str_ret, #str wr JMPRET b, #label_or_binary_ret nr out_binary JMPRET binary2_ret, #binary wr label_or_binary_ret JMPRET b, #b nr binary MOV tmp_ctr, #$003 wr ROR tmp, #$008 wr binary2 MOV char, #$024 wr JMPRET tx_ret, #tx wr bin_loop MOV char, tmp wr ROL tmp, #$004 wr AND char, #$00F wr SUB char, #$009 nr, wz, wc if_nc_and_nz ADD char, #$037 wr if_c_or_z ADD char, #$030 wr JMPRET tx_ret, #tx wr DJNZ tmp_ctr, #bin_loop wr binary2_ret JMPRET b, #b nr align SUB tmp, position nr, wz, wc if_c_or_z JMPRET b, #align_ret nr MOV char, #$020 wr JMPRET tx_ret, #tx wr JMPRET b, #align nr align_ret JMPRET b, #b nr tx SUB char, #$00A nr, wz if_z MOV position, #b wr if_nz ADD position, #$001 wr OR char, #vars_size wr SHL char, #$002 wr OR char, #$001 wr MOV bitcount, #$00B wr MOV timer, CNT wr ADD timer, bittime wr tx_loop SHR char, #$001 wr, wc MUXC OUTA, pinmask wr WAITCNT timer, bittime wr DJNZ bitcount, #tx_loop wr tx_ret JMPRET b, #b nr find_label MOV str_address, #vars_end wr SHL str_address, #$002 wr ADD str_address, PAR wr check_label RDWORD char, str_address ADD str_address, #$002 wr ROR char, #$00F wr AND char, #$001 nr, wc if_c MOV str_address, #b wr if_c JMPRET b, #find_label_ret nr ROL char, #$00F wr SUB char, tmp nr, wz if_z JMPRET b, #find_label_ret nr skip_label RDBYTE char, str_address wz ADD str_address, #$001 wr if_nz JMPRET b, #skip_label nr AND str_address, #$001 nr, wc if_c ADD str_address, #$001 wr JMPRET b, #check_label nr find_label_ret JMPRET b, #b nr code_end long $00000000 src long $00000000 dst long $00000000 flags long $00000000 pc long $00000000 cond long $00000000 imm long $00000000 tmp long $00000000 tmp_ctr long $00000000 char long $00000000 str_address long $00000000 bitcount long $00000000 bittime long $000002B6 timer long $00000000 pinmask long $40000000 conditions_addr long $000001F5 operations_addr long $00000217 registers_addr long $000001E1 code_size long $000000EC data_size long $0000016D vars_size long $0000002C flags_str_addr long $0000026F long_str_addr long $00000281 byte_str_addr long $00000283 opcode_addr long $00000000 position long $00000000 prologue long $204E4F43 long $4B4C435F long $45444F4D long $4154583D long $502B314C long $36314C4C long $585F2C58 long $52464E49 long $353D5145 long $30303030 long $500A3030 long $6D204255 long $676F630A long $74696E69 long $202C3028 long $402C6240 long $440A2962 long $000A5441 vars_end byte $000,$000,"b",$000,$014,$000,"m","a","i","n","l",$000,",",$000,"n","o" byte "_","l","a","b","e","l",$000,$000,"@",$000,"n","o","n","_","m","e" byte "m",$000,"@",$000,"n","o","p","_",$000,$000,"S",$000,"n","o","_","o" byte "p","r","n","d","s",$000,"b",$000,"v","a","r","s","_","l","o","o" byte "p",$000,"i",$000,"n","o","_","v","a","r","_","l","a","b","e","l" byte $000,$000,"{",$000,"p","r","i","n","t","_","d","a","t","a",$000,$000 byte "}",$000,"d","a","t","a","_","l","o","o","p",$000,$082,$000,"c","o" byte "m","m","a",$000,$084,$000,"b","i","t","s",$000,$000,$092,$000,"b","i" byte "n",$000,$093,$000,"n","x","t",$000,$09B,$000,"s","t","r",$000,$09C,$000 byte "i","d","x","_","s","t","r",$000,$09D,$000,"s","e","e","k","_","l" byte "o","o","p",$000,$0A1,$000,"d","o","n","e",$000,$000,$0A6,$000,"i","d" byte "x","_","s","t","r","_","r","e","t",$000,$0A6,$000,"s","t","r","_" byte "r","e","t",$000,$0A7,$000,"l","a","b","e","l","_","o","r","_","b" byte "i","n","a","r","y","_","d","s","t",$000,$0A9,$000,"l","a","b","e" byte "l","_","o","r","_","b","i","n","a","r","y",$000,$0B1,$000,"n","o" byte "r","e","g",$000,$0B6,$000,"o","u","t","_","b","i","n","a","r","y" byte $000,$000,$0B7,$000,"l","a","b","e","l","_","o","r","_","b","i","n" byte "a","r","y","_","r","e","t",$000,$0B7,$000,"l","a","b","e","l","_" byte "o","r","_","b","i","n","a","r","y","_","d","s","t","_","r","e" byte "t",$000,$0B8,$000,"b","i","n","a","r","y",$000,$000,$0BA,$000,"b","i" byte "n","a","r","y","2",$000,$0BC,$000,"b","i","n","_","l","o","o","p" byte $000,$000,$0C4,$000,"b","i","n","a","r","y","2","_","r","e","t",$000 byte $0C4,$000,"b","i","n","a","r","y","_","r","e","t",$000,$000,$0C5,$000 byte "a","l","i","g","n",$000,$0CA,$000,"a","l","i","g","n","_","r","e" byte "t",$000,$0CB,$000,"t","x",$000,$000,$0D4,$000,"t","x","_","l","o","o" byte "p",$000,$0D8,$000,"t","x","_","r","e","t",$000,$000,$0D9,$000,"f","i" byte "n","d","_","l","a","b","e","l",$000,$000,$0DC,$000,"c","h","e","c" byte "k","_","l","a","b","e","l",$000,$0E5,$000,"s","k","i","p","_","l" byte "a","b","e","l",$000,$000,$0EB,$000,"f","i","n","d","_","l","a","b" byte "e","l","_","r","e","t",$000,$000,$0EC,$000,"c","o","d","e","_","e" byte "n","d",$000,$000,$0EC,$000,"o","p","c","o","d","e",$000,$000,$0ED,$000 byte "s","r","c",$000,$0EE,$000,"d","s","t",$000,$0EF,$000,"f","l","a","g" byte "s",$000,$0F0,$000,"p","c",$000,$000,$0F1,$000,"c","o","n","d",$000,$000 byte $0F2,$000,"i","m","m",$000,$0F3,$000,"t","m","p",$000,$0F4,$000,"t","m" byte "p","_","c","t","r",$000,$0F5,$000,"c","h","a","r",$000,$000,$0F6,$000 byte "s","t","r","_","a","d","d","r","e","s","s",$000,$0F7,$000,"b","i" byte "t","c","o","u","n","t",$000,$000,$0F8,$000,"b","i","t","t","i","m" byte "e",$000,$0F9,$000,"t","i","m","e","r",$000,$0FA,$000,"p","i","n","m" byte "a","s","k",$000,$0FB,$000,"c","o","n","d","i","t","i","o","n","s" byte "_","a","d","d","r",$000,$0FC,$000,"o","p","e","r","a","t","i","o" byte "n","s","_","a","d","d","r",$000,$0FD,$000,"r","e","g","i","s","t" byte "e","r","s","_","a","d","d","r",$000,$000,$0FE,$000,"c","o","d","e" byte "_","s","i","z","e",$000,$0FF,$000,"d","a","t","a","_","s","i","z" byte "e",$000,$000,$001,"v","a","r","s","_","s","i","z","e",$000,$001,$001 byte "f","l","a","g","s","_","s","t","r","_","a","d","d","r",$000,$000 byte $002,$001,"l","o","n","g","_","s","t","r","_","a","d","d","r",$000 byte $003,$001,"b","y","t","e","_","s","t","r","_","a","d","d","r",$000 byte $004,$001,"o","p","c","o","d","e","_","a","d","d","r",$000,$005,$001 byte "p","o","s","i","t","i","o","n",$000,$000,$006,$001,"p","r","o","l" byte "o","g","u","e",$000,$000,$018,$001,"v","a","r","s","_","e","n","d" byte $000,$000,$0FF,$0FF,"P","A","R",$000,"C","N","T",$000,"I","N","A",$000 byte "I","N","B",$000,"O","U","T","A",$000,"O","U","T","B",$000,"D","I" byte "R","A",$000,"D","I","R","B",$000,"C","T","R","A",$000,"C","T","R" byte "B",$000,"F","R","Q","A",$000,"F","R","Q","B",$000,"P","H","S","A" byte $000,"P","H","S","B",$000,"V","C","F","G",$000,"V","S","C","L",$000 byte $000,$000,$000,$000,$000,"i","f","_","n","c","_","a","n","d","_","n" byte "z",$000,"i","f","_","n","c","_","a","n","d","_","z",$000,"i","f" byte "_","n","c",$000,"i","f","_","c","_","a","n","d","_","n","z",$000 byte "i","f","_","n","z",$000,"i","f","_","c","_","n","e","_","z",$000 byte "i","f","_","n","c","_","o","r","_","n","z",$000,"i","f","_","c" byte "_","a","n","d","_","z",$000,"i","f","_","c","_","e","q","_","z" byte $000,"i","f","_","z",$000,"i","f","_","n","c","_","o","r","_","z" byte $000,"i","f","_","c",$000,"i","f","_","c","_","o","r","_","n","z" byte $000,"i","f","_","c","_","o","r","_","z",$000,$000,"N","O","P",$000 byte "W","R","B","Y","T","E",$000,"W","R","W","O","R","D",$000,"W","R" byte "L","O","N","G",$000,"R","D","B","Y","T","E",$000,"R","D","W","O" byte "R","D",$000,"R","D","L","O","N","G",$000,"H","U","B","O","P",$000 byte "?",$000,"?",$000,"?",$000,"?",$000,"R","O","R",$000,"R","O","L",$000 byte "S","H","R",$000,"S","H","L",$000,"R","C","R",$000,"R","C","L",$000 byte "S","A","R",$000,"R","E","V",$000,"M","I","N","S",$000,"M","A","X" byte "S",$000,"M","I","N",$000,"M","A","X",$000,"M","O","V","S",$000,"M" byte "O","V","D",$000,"M","O","V","I",$000,"J","M","P","R","E","T",$000 byte "A","N","D",$000,"A","N","D","N",$000,"O","R",$000,"X","O","R",$000 byte "M","U","X","C",$000,"M","U","X","N","C",$000,"M","U","X","Z",$000 byte "M","U","X","N","Z",$000,"A","D","D",$000,"S","U","B",$000,"A","D" byte "D","A","B","S",$000,"S","U","B","A","B","S",$000,"S","U","M","C" byte $000,"S","U","M","N","C",$000,"S","U","M","Z",$000,"S","U","M","N" byte "Z",$000,"M","O","V",$000,"N","E","G",$000,"A","B","S",$000,"A","B" byte "S","N","E","G",$000,"N","E","G","C",$000,"N","E","G","N","C",$000 byte "N","E","G","Z",$000,"N","E","G","N","Z",$000,"C","M","P","S",$000 byte "C","M","P","S","X",$000,"A","D","D","X",$000,"S","U","B","X",$000 byte "A","D","D","S",$000,"S","U","B","S",$000,"A","D","D","S","X",$000 byte "S","U","B","S","X",$000,"C","M","P","S","U","B",$000,"D","J","N" byte "Z",$000,"T","J","N","Z",$000,"T","J","Z",$000,"W","A","I","T","P" byte "E","Q",$000,"W","A","I","T","P","N","E",$000,"W","A","I","T","C" byte "N","T",$000,"W","A","I","T","V","I","D",$000,$000,"n","r",$000,"w" byte "r",$000,"n","r",","," ","w","c",$000,"w","r",","," ","w","c",$000 byte "n","r",","," ","w","z",$000,"w","r",","," ","w","z",$000,"n","r" byte ","," ","w","z",","," ","w","c",$000,"w","r",","," ","w","z","," byte " ","w","c",$000,$000,"w","c",$000,"w","z",$000,"w","z",","," ","w" byte "c",$000,$000,$000,"l","o","n","g"," ",$000,$000,$000,"b","y","t","e" byte " ",$000,$000,$000
CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 VAR byte s[4000] word p, r PRI dmp | i, c r~~ repeat i from 0 to p - 1 case c := s[i] 1: str(string(32,32,98,117,102,40,115,116,114,105,110,103,40,34)) 2: str(string(34,41,41,13)) other: tx(c) str(string(32,32,100,109,112,13)) PRI buf(i) s[p++] := 1 bytemove(@s[p], i, strsize(i)) p += strsize(i) s[p++] := 2 str(i) PRI str(i) | c repeat while c := byte[i++] if (r == 0 and c == 92) c := 13 tx(c) PRI tx(i) | t t := cnt i := (i | $300) << 1 repeat 11 waitcnt(t += 8333) outa[30] := i & 1 i >>= 1 PUB go waitcnt(cnt + clkfreq + outa[30]~~ + dira[30]~~) buf(string("CON\\ _clkmode = xtal1 + pll16x\ _xinfreq = 5_000_000\\VAR\\ byte s[4000]\ ")) buf(string(" word p, r\\PRI dmp | i, c\\ r~~\ repeat i from 0 to p - 1\ case c := s[i]\")) buf(string(" 1: str(string(32,32,98,117,102,40,115,116,114,105,110,103,40,34))\ 2:")) buf(string(" str(string(34,41,41,13))\ other: tx(c)\ str(string(32,32,100,109,112,13))")) buf(string("\\PRI buf(i)\\ s[p++] := 1\ bytemove(@s[p], i, strsize(i))\ p += strsize(i)\ ")) buf(string(" s[p++] := 2\ str(i)\\PRI str(i) | c\\ repeat while c := byte[i++]\ if (r =")) buf(string("= 0 and c == 92)\ c := 13\ tx(c)\\PRI tx(i) | t\\ t := cnt\ i := (i | ")) buf(string("$300) << 1\ repeat 11\ waitcnt(t += 8333)\ outa[30] := i & 1\ i >>= 1\")) buf(string("\PUB go\\ waitcnt(cnt + clkfreq + outa[30]~~ + dira[30]~~)\")) dmp
-Phil
Yours is "beautiful" and "interesting" in exactly the opposite way of the one I cited above. Very well done. Impressive.
Dave
So I would say that this means that the generated file is a valid quine and the original source is not???
It took quite a few lines of code to generate Spin source from bytecodes. I had to limit the number of operators I used, and I use "repeat while" to do all my loops and if statements.