x86 Quine: These 12 Bytes of Machine Code Print Themselves (2005)
susam.net
susam.net
It is like “10 LIST” quine.
For the machine code, the memory is THE source, and this code simply reads it because it can.
Imagine a quine in machine code running on an architecture where it is not allowed to read the code segment. This quine will not work there.
The REAL quine should generate the output purely via output data transformation encoded INTO the source, without any assumption of the runtime.
Those strings might or might not be kept in a different segment, depending on the architecture, but can you define "machine code" in an abstract enough way to allow some kind of string printing in general without self-reference?
Things are a bit more murky with variable-length instructions, but basically you are not allowed to read as data any address that is ever read as part of instruction decoding.
How do you know which addresses those will be? If the underlying architecture and OS permit reads or writes of code segments and/or execution of data segments, this set of addresses is literally undecidable.
You don't have to know these adresses beforehand, so you can just run the program to collect them and check. Or you roll up your sleeves and do some maths to compute (an overapproximation of) that set for the specific program you're interested in, which may be your only option if your architecture is nondeterministic.
Somewhat related: http://cm.bell-labs.com/who/ken/trust.html
Somewhat related: mRNA
I have no idea if its just my font or if its a unicode change. I guess U+FE0E might change it back, but i didnt test because its difficult to input on my phone.
Regarding the sentence: "The first instruction clears the direction flag.", I noticed that cld is the second instruction in the listing, I suppose that is a small mistake in the article?
It is the disassembly that was inaccurate. It seems I had the disassembly of a slightly different version of the program in this post. I used the 12 bytes at the top of this post to recreate the .COM file just now and I have updated the post with the corresponding disassembly. It should now be accurate. Thank you, once again, for noticing this issue and commenting about it here.
A C program that reverse engineered itself by reading its own machine code is also not a quibe, to be clear.
It gives another version that separates code and data. The challenge is that in x86 assembler, there is no distinction between code and data at the cpu-acting-on-memory level - either way you're reading memory and indeed reading some of the same byte values of member.
So in 16-bit and 32-bit x86 CPUs, starting with 80286, it was possible to distinguish code memory and data memory, without allowing any mixing between them. The distinction was possible even in the assembly source text, for some of the more sophisticated assemblers, because you could declare the segments used, with all their attributes, and the assembler could check if the segments were used correctly, based on ASSUME directives that specified the content of the segment registers.
In the more recent 64-bit x86 CPUs, it is possible to prohibit instruction fetches from a memory page, but it is not possible to prohibit data reads from a memory page with code.
#include <stdio.h>
int main(int c,char** v){char*s="#include <stdio.h>%cint main(int c,char** v){char*s=%c%s%c;printf(s,10,34,s,34,10);}%c";printf(s,10,34,s,34,10);}
Surely this should count as a non-cheated quine? Still, parts of the code (namely, the contents of string s) are embedded directly in the binary: % clang -std=c99 -pedantic quine.c -o quine; strings quine | grep include
#include <stdio.h>%cint main(int c,char** v){char*s=%c%s%c;printf(s,10,34,s,34,10);}%c
Even though parts of the original source survive in the binary and are passed as pointers to a print function, the source code itself doesn't get read at compile or runtime (aside from being read once into the compiler).If it's OK to read parts of the loaded binary to use as strings, I don't see why it wouldn't be OK to read the whole loaded binary, as long as you touch the source code file. I'd simply accept that the platform allows for some fairly trivial quines.