Probably because it's the "generic way" to cover all cases. Remember that for/step/next can go in any direction with any sign on the increment.
You used parameters on both the increment and the end-bound. The compiler has no way to know if you are going to count up or down, and if th end-bound is higher or lower than the start bound.
My guess is this is a way to get code that will work whatever you put in n and s (just a guess, I'm too tired to try and see if that is the case).
Also it makes copies of the parameters to prevent outside interference (like changing s or n during the enumeration).
=== UPDATE ===
I doubt anybody is still watching that question but I came back to this nugget just for the sake of completeness, and because I had some time.
What VB is doing is a bit sneaky. The bit shift of S basically creates an integer based on the sign of S (it copies the MSB of s, ending up with &hFFFFFFFF is S is negative and &h00000000 if S is positive).
XOR of an integer value with -1 is equivalent to (-value-1). XOR with 0 is obviously a NOP.
So if s is negative, it reverses both values (the -1 cancel each other) to compare them, effectively reversing the order of comparison without the need or a conditional, and thus no jump in the program flow.
If s is positive it just compares them.
so, for s<0 you end up with
while (-i-1)<=(-n-1)
==> while -i <= -n
==> while i>=n
for s>0 you end up with
while i <= n
Takes me back to my 68k ASM days where such tricks where the everyday stuff (such as XOR.l D0,D0 because XORing a register with itself was faster than loading zero in it...) :p