Weird code
George Robbert
ghr at wucs.UUCP
Sun Oct 20 05:51:45 AEST 1985
>Ok you wizards out there, why does this program do what it does?
>Here are a couple of hints:
> 1) It only works on Vaxes
> 2) The same idea is used to initialize the UNIBUS adapters
>main()
>{
> register int x, y;
> int i;
> int func();
>
> fix((int *)func);
> x = 1; y = 5;
> for (i = 1; i <= 10; i++) {
> func(1,5);
> printf("x = %d, y = %d\n",x,y);
> }
>}
>func(x,y)
>int x,y;
>{
> register int a,b;
>
> a += a; b *= 5;
> x--; y++;
>}
>
>fix(f)
>int *f;
>{
> *f &= ~0xc00;
>}
>% cc reg.c -N -o reg
>% reg
>x = 2, y = 25
>x = 4, y = 125
>x = 8, y = 625
>x = 16, y = 3125
>x = 32, y = 15625
>x = 64, y = 78125
>x = 128, y = 390625
>x = 256, y = 1953125
>x = 512, y = 9765625
>x = 1024, y = 48828125
>Brian Justice, Iowa State University
>UUCP: {okstate||umn-cs||csu-cs}!isucs1!justice CSNET: justice at iowa
The reason that you get the strange behavior of x and y is due
to fix's clearing 2 bits of the register save mask for func().
All functions on the VAX begin with a word (16 bit) that is the register
save mask. This word indicates which registers should be pushed on
the stack at function call time and restored on return. Bit n set
corresponds to saving register n. Therefore, *f &= ~0xc00; clears the
mask for r10 and r11. These just happen to be the two registers that
x and y are stored in. They also happen to be the ones that a and b
are stored in. Thus, since they are not saved and restored when
func(1,5) is called, the changes to a and b are actually changes to
x and y. This is why the code does what it does on the VAX. I don't
know why they do this to initialize unibus adapters. (except maybe
to minimize function call overhead by reducing the registers saved &
restored at each call.)
George Robbert, Washington University
ghr at wucs.UUCP ...!ihnp4!wucs!ghr
More information about the Comp.unix.wizards
mailing list