(1) Though it is bad for most of time but still I feel more contended sometimes with it, especially for complex code.
(2) Even if this transparency is at superficial level with optimising compilers, but there are very few high level optimisation applied to C code and that too in the form of loop unrolling, tail call optimisation, loop interchange etc.
I bet these two ideas would go well together.
https://0xcd80.wordpress.com/2011/04/29/linux-x86-shellcodin...
const char main[] =
"UH\x89\xe5\xb8\1\0\0\0\xbb\1\0\0\0g\x8d"
"5\x10\0\0\0\xba\r\0\0\0\xf\5\xb8\x3c\0\0\0"
"1\xdb\xf\5Hello World!\n]\xc3";I remember 20 years or ago writing my first C/C++ function where I popped out to inline ASM. I was like, wow! I'm in complete control of this box! (It was mostly copied code. My ASM-foo is weak) I really liked the fact that I could either code in these really abstract types -- or be concerned with what the stack looks like on entering a function. So I _think_ I know the answer to the question.
Instead of ignoring the error, I was thinking that you could just mangle the link file and make the entry point whatever you want, right? I could have a program that consisted of "void x", then continue along the lines of the articles with the number list.
Heck, once you start pulling the threads apart like this, the entire structure falls apart. Your source code could look like anything you want it to look like. And that's cool.
On the topic of "executable ASCII", the EICAR test file is an interesting example: http://en.wikipedia.org/wiki/EICAR_test_file
Place your string after a "call" instruction, then when you are inside the call, the address of the string is on the stack, you can pop it in any register you want.
But as far as the TA goes, most people who have an interest in C and programming will look at the source and say to themselves "Oh, byte values of machine code being executed, yes very clever but do the assignment again properly."
That being said, I wouldn't rule out a bored TA opening the file not seeing a printf and assigning a grade based on submitting something.
char main[] = {
movl(1, eax),
movl(1, ebx),
movl(message, esi),
movl(13, edx),
syscall(),
movl(60, eax),
xorl(ebx, ebx),
syscall(),
};
Obviously there are some technical difficulties like handling literal values and code sections, but it could be a fun hack, and I've love to see what someone could come up with. main(){
int i=512;
do
write(1," :-)\b\b\b\b",9),usleep(i);
while(--i);
}
So, it moves a smiley on the screen, at increasing speed.For other obfuscated fun, see this poem/tree printer in 505 bytes[0], or this program:
main(G){10<putchar(11^--G?89-(0x1F&2846984999544829581>>5*G):10)&&main(2+G);}
[0] - https://github.com/lelandbatey/tiny_tree_printerLet's begin with that big constant. The values of
89-(0x1F&2846984999544829581>>5*G)
for successive choices of G are: 76 69 76 65 78 68 66 65 84 69 89 74 87. "Obviously" these are character indices; the characters are L,E,L,A,N,D,B,A,T,E,Y,J,W. (I remark that Leland was the first name of the founder of Stanford University and conjecture that the author of the code works at, or studied at, Stanford. And then I look up at the username of the person who posted it and feel a bit stupid.)Now, what's the argument to putchar? It has the form
11^--G ? thing1 : thing2
so it decrements G, and then if the result is anything other than 11 it evaluates thing1; but if the result is 11 it evaluates thing2 instead. In this case, thing1 is our LELANDBATEY generator and thing2 is 10 (= newline).So far, so good. One more step out. What comes before the && inside main? It looks like this:
10<putchar(stuff)
and the return value from putchar is (barring I/O failures) the same as what's fed into it. So, putting the above together, when G isn't 12 we'll decrement G, write out a character from LELANDBATEYJW (indexed by G), and this thing will be true; when G is 12 we'll decrement G, write out a newline, and this thing will be false.Nearly there. Now the whole thing looks like
main(G) { thing_above && main(2+G); }
so when G isn't 12 it will decrement G, write out a character from LELANDBATEY, and immediately call main with G+2 (which is 1 more than G started out as); but if G is 12 on entry to main it will decrement G, write out a newline, and then return (perhaps to a previous stack frame which will also return, and so on until exit).OK. So, I guess this program is intended to be invoked with no command-line args. Then G (= argc) will be 1. We'll write out characters 0, 1, 2, ..., 10 of the LELANDBATEY string (getting exactly that far) at which point G will be 12 on entry to the next main call. Newline, exit. Done.
(In case it isn't clear: it outputs "LELANDBATEY\n".)
No offence, I hope, but this is really tame compared with typical short-short IOCCC entries. Here's an example from the 22nd IOCCC. It's short enough to tweet.
char a;float b,c;main(d){for(;d>2e3*c?c=1,scanf(" %c%f",&a,&c),d=55-a%32*9/5,b=d>9,d=d%13-a/32*12:1;a=2)++d<24?b*=89/84.:putchar(a=b*d);}
See http://www.ioccc.org/2013/endoh3/hint.html for more about this; it interprets tunes written in a simple musical notation and generates raw audio data.Also, I wrote a program to generate these. So here's one for you:
main(O){10<putchar(5^--O?77-(31&2278424678>>5*O):10)&&main(2+O);}
In fact, I originally found this style of tiny C program on Hacker News nearly two years ago. Here's the link to the original: https://news.ycombinator.com/item?id=5524428Still, was a nifty trick that allowed you to get more performance out of a language that wasn't very fast to begin with.
I don't know, something about that just didn't sit right with me.
#include "X.h"
X x;
void main(){} int main = 0;
This code compiles (cleanly!), but segfaults.EDIT: Your original post contained
int main=0; main=0;I'm afraid I may be a victim of Poe's law here, but this attitude is... distressing. It completely discounts the value of problem solving, which, once upon a time, was the entire point of the profession.
An example of that is the article itself which leverages the gained information from SO to solve the real problem.
Also arcane knowledge is not the same thing as problem solving.
I'm not sure if you even bothered to read the article... since that was the very next sentence. I, too, wanted to give the author the benefit of the doubt and assume it was mere information gathering, which is a good thing, but the next sentence shows that the intent is to solve the problem from start to finish with Google.
Maybe it's ARM, or MIPS, or… Followup problem: write a sequence of bytes that performs a jump on one architecture, and something harmless or reversible on the other(s).
movq $0x2000004, %rax ; // BSD syscalls are divided into classes.
movq $1, %rdi ; // 64-bit registers use %rdi instead of %ebx
lea message(%rip), %rsi; // Relative Address of message
movq $13, %rdx ; // Same Length
syscall ; // x86-64 ASM syscall
movq $0x2000001, %rax ; // Exit Syscall
movq $0, %rdi;
syscall
message: .ascii "Hello World!\n"; echo 'const int main[]={3850979413,184,3234285568,33554436,29869896,1207959552,1652109,3343384576,3522,1208291072,114887,3343385088,199,1208291072,1869376613,1919899424,169960556};'>t.c&&gcc t.c&&./a.out
But it is too long to tweet[Edit]
Less compact but more readable:
echo 'const int main[] = { 3850979413, 184, 3234285568, 33554436, 29869896, 1207959552, 1652109, 3343384576, 3522, 1208291072, 114887, 3343385088, 199, 1208291072, 1869376613, 1919899424, 169960556};' > test.c && gcc -Wall test.c -o test && ./test echo 'const int main[]={1208,114434,2370306048,2101,834048,84869120,1818577091,1461743468,1684828783,10};'|cc -xc -ot -&&./t
The trick is to use retq instead of a sys call to exit and to strip some of the code that the compiler create when you call a function (pushq %rpb; moveq %rsp, %rbp; movl $0x0, eax;)