mildly obfuscating c

Oleg Kiselev oleg at birtch.UUCP
Wed Dec 11 15:05:55 AEST 1985


In article <564 at puff.UUCP> tom at puff.UUCP writes:
>ok, guys, now i will admit that the below code is *not* kosher. 
>but the question still remains, if you run this program, what will
>your output be?  does the machine you compile it on make
>a difference?  does defining ARG to be something, say 999,
>make a difference?   what if VAR were auto or static?
>
>-------------------------------------------------------------
># define ARG
># define VAR register
># define CALL(x) (*(int (*)()) (x))(ARG)
>
>main() {
>    VAR thing = 0;
>stuff:
>    printf("here it goes, thing is %d\n",thing);
>    if (!thing++) 
>        CALL(stuff);
>    printf("one there it went, thing is %d\n",thing);
>    printf("two there it went, thing is still %d\n",thing);
>}
>
>
>/* lint outputs
>test.c:
>test.c(8): warning: questionable conversion of function pointer
>*/
>-------------------------------------------------------------
>
>note the lint output.  no kidding.
.......[DELETED]........
>on a pyramid, this is the bizarre result:
>
>-------------------------------------------------------------
>here it goes, thing is 0
>here it goes, thing is 536151860
>one there it went, thing is 536151861
>two there it went, thing is still 536151861
>one there it went, thing is 1
>two there it went, thing is still 1
>-------------------------------------------------------------

Actually, this is not too bizarre....

This is the way it works on our Pyramid:
The way the code is written, declaration of "thing" precedes the label.
So, the routine call to stuff jumps to _stuff symbol address. _thing symbol
is initialized by code located BEFORE _stuff address, probably by 
"movw $0,<whatever>". Then there follows a printf call. If you do not take care
of placing you variables outside the routine ( making them global) or declaring
them static, Pyramid's C compiler will optimize EVERY possible variable to be
"register" (&'d things are exempt, I think). So, what happens in THIS program is
that the assignment to _thing is actually a register assignment. When you
call a subroutine, the register frame on Pyramid shifts and a new set of 
registers is presented to the routine to use as local automatic storage. And
the register where the code expects to find _thing ( some l-register?) is now
uninitialized. 

That would mean also that if more than n (8?16?) calls are made recursively
something will change ( when Pyramid's processor runs out of its 528(?) 
registers and has to push things on stack). Hey, anybody has time to check that?
-- 
Disclamer: My employers go to church every Sunday, listen to Country music,
and donate money to GOP. I am just a deviant.
+-------------------------------+ Don't bother, I'll find the door!
| "VIOLATORS WILL BE TOAD!"	|                       Oleg Kiselev. 
|		Dungeon Police	|...!{trwrb|scgvaxd}!felix!birtch!oleg
--------------------------------+...!{ihnp4|randvax}!ucla-cs!uclapic!oac6!oleg



More information about the Comp.lang.c mailing list