前言
和学长讨论x64函数传参的问题, 用哪几个寄存器传前4个参,记不清了,做个试验.
记录
// Test1230.cpp : Defines the entry point for the console application.
//
// x64传参约定
// x64传参是fastcall调用约定
// x64传参时, 参数<=4个时,参数从右往左用寄存器传参
// x64传参时, 参数>4个时,参数从右往左前4个参数用寄存器传参, 剩下参数用栈传参(最右面的参数先入栈)
// 但是我想不起来用哪4个寄存器传参了, 做个试验.
#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
void fnTest(int iParam1, int iParam2, int iParam3, int iParam4, int iParam5, int iParam6);
int _tmain(int argc, _TCHAR* argv[])
{
// 调用 fnTest 之前的反汇编实现
/**
000000013F6C10C0 | 48 89 54 24 10 | mov qword ptr ss:[rsp+10],rdx | test1230.cpp:15
000000013F6C10C5 | 89 4C 24 08 | mov dword ptr ss:[rsp+8],ecx |
000000013F6C10C9 | 57 | push rdi |
000000013F6C10CA | 48 83 EC 30 | sub rsp,30 |
000000013F6C10CE | 48 8B FC | mov rdi,rsp |
000000013F6C10D1 | B9 0C 00 00 00 | mov ecx,C |
000000013F6C10D6 | B8 CC CC CC CC | mov eax,CCCCCCCC |
000000013F6C10DB | F3 AB | rep stosd dword ptr ds:[rdi],eax |
000000013F6C10DD | 8B 4C 24 40 | mov ecx,dword ptr ss:[rsp+40] |
000000013F6C10E1 | C7 44 24 28 06 00 00 00 | mov dword ptr ss:[rsp+28],6 | test1230.cpp:16
000000013F6C10E9 | C7 44 24 20 05 00 00 00 | mov dword ptr ss:[rsp+20],5 |
000000013F6C10F1 | 41 B9 04 00 00 00 | mov r9d,4 |
000000013F6C10F7 | 41 B8 03 00 00 00 | mov r8d,3 |
000000013F6C10FD | BA 02 00 00 00 | mov edx,2 |
000000013F6C1102 | B9 01 00 00 00 | mov ecx,1 |
000000013F6C1107 | E8 F9 FE FF FF | call <test1230.@ILT+0(?fnTest@@YAXHHHHHH@Z)> |
*/
// 可以看到参数传递过程
// 超过4个参数后, 参数从右往左入栈
// push Param6 // 参数6
// push Param5 // 参数5
// 前4个参数进入寄存器,老手的口头禅, 所谓的 : cd89
// mov r9d, 4 // 参数4
// mov r8d, 3 // 参数3
// mov edx, 2 // 参数2
// mov ecx, 1 // 参数1
// 如果一个函数很复杂, 在release版下不会优化成内联实现, 也符合这种传参约定
fnTest(1, 2, 3, 4, 5, 6);
return 0;
}
// 这函数太简单了, 编译成release版, 内联了.
// 用Debug版看吧
void fnTest(int iParam1, int iParam2, int iParam3, int iParam4, int iParam5, int iParam6)
{
printf("iParam1 = %d\r\n", iParam1);
printf("iParam2 = %d\r\n", iParam2);
printf("iParam3 = %d\r\n", iParam3);
printf("iParam4 = %d\r\n", iParam4);
printf("iParam5 = %d\r\n", iParam5);
printf("iParam6 = %d\r\n", iParam6);
}