The reason the calls behave different is they bind to very different methods.
The == case will bind to the static reference equality operator. There are 2 independent boxed int values created hence they are not the same reference.
In the second case you bind to the instance method Object.Equals. This is a virtual method which will filter down to Int32.Equals and this checks for a boxed integer. Both integer values are 0 hence they are equal