Matthew, from your answers in this forum I recall that you are one of the experienced guys around here. So, please treat my answer just as a suggestion and it might just complement what you found out yourself so far.
Let's first clarify, what exactly is meant by stack alignment. I'd define it as:
The minimum size the CPU uses for a push operation.
By that definition, I would stay away from comparing the addresses of stack-based variables. A compiler generally allocates the local variables of a function by just subtracting the required total size from the stack pointer. Inside that memory contingent it arranges variables just as it likes, using packing, reordering, etc. So, the address difference of two single-byte variables might very well be 1, or -1, or anything else.
What I would try to use is the sequence in which the compiler pushed arguments on the stack. Usually that will be either left to right or right to left, but in any case in strict sequence. That you can build upon, because otherwise the var_args mechanism would not work or at least would be very hard to implement.
So I'd write a little function like this:
UINT ArgAddressDiff (char arg1, char arg2, ...)
{
return abs (&arg1 - &arg2);
}
Optimization might put the arguments into registers, though. That's the reason I included the "..." varg_args declarator. That might prevent such an optimization, but I am not sure.
You could also try to pass the two arguments as the variable arguments of the function, in which the compiler has no chance to optimize them away. That would require some tweeking with the va_list and va_start macros. I haven't tried that yet, though.
I hope that contributes somewhat to your solution.