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