The first four integer arguments will be passed in registers. Integer values will be passed (in order left to right) in RCX, RDX, R8, and R9. Arguments four and higher will passed onto the stack. All arguments are right justified in registers. This is done so the callee can ignore the upper bits of the register if need be and can access only the portion of the register necessary.
Floating-point and double-precision arguments are passed in XMM0 – XMM3 (up to 4) with the integer slot (RCX, RDX, R8, and R9) that would normally be used for that cardinal slot being ignored (see example) and vice versa.
Intrinsic functions that do not allocate stack space and do not call other functions can use other volatile registers to pass additional register arguments because there is a tight binding between the compiler and the intrinsic function implementation. This is a further opportunity for improving performance.
The callee has the responsibility of dumping the register parameters into their shadow space if needed.
The following table summarizes how parameters are passed:
Parameter type | How passed |
---|---|
Floating point |
First 4 parameters – XMM0 through XMM3. Others passed on stack. |
Integer |
First 4 parameters – RCX, RDX, R8, R9. Others passed on stack. |
Aggregates (8, 16, 32, or 64 bits) and __m64 |
First 4 parameters – RCX, RDX, R8, R9. Others passed on stack. |
Aggregates (other) |
By pointer. First 4 parameters passed as pointers in RCX, RDX, R8, and R9 |
__m128 |
By pointer. First 4 parameters passed as pointers in RCX, RDX, R8, and R9 |