x64 传参再分析
本帖最后由 zaas 于 2014-11-6 21:51 编辑老飘写的还有一点没看懂:为啥第五个参数从rsp + 20开始??自己写代码测试下:
#include <windows.h>
INT64 xxx(INT64 a,INT64 b ,INT64 c,INT64 d,INT64 e,INT64 f,INT64 g,INT64 h)
{
return a + b + c + d + e + f + g + h;
}
int yyy(int a,int b ,int c,int d,int e,int f,int g,int h)
{
return a + b + c + d + e + f + g + h;
}
int _tmain(int argc, _TCHAR* argv[])
{
INT64 a,b,c,d,e,f,g,h;
int p,q,r,s,t,u,v,w;
scanf("%I64d %I64d %I64d %I64d %I64d %I64d %I64d %I64d",&a,&b,&c,&d,&e,&f,&g,&h);
printf("%I64d\n",xxx(a,b,c,d,e,f,g,h));
fflush(stdin);
scanf("%d %d %d %d %d %d %d %d",&p,&q,&r,&s,&t,&u,&v,&w);
printf("%d\n",yyy(p,q,r,s,t,u,v,w));
return 0;
}传参:
000000013FDF1147 mov rax,
000000013FDF114F mov ,rax
000000013FDF1154 mov rax,
000000013FDF115C mov ,rax
000000013FDF1161 mov rax,
000000013FDF1169 mov ,rax
000000013FDF116E mov rax,
000000013FDF1176 mov ,rax
000000013FDF117B mov r9,
000000013FDF1183 mov r8,
000000013FDF118B mov rdx,
000000013FDF1190 mov rcx,
000000013FDF1195 call @ILT+0(?xxx@@YA_J_J0000000@Z)rcx,rdx,r8,r9,,,,
到函数里边:
00000013FDF1030 mov ,r9
000000013FDF1035 mov ,r8
000000013FDF103A mov ,rdx
000000013FDF103F mov ,rcx也就是说到函数里边,还是先把rcx,rdx,r8,r9放到堆栈对应的位置去。。。
即使被调用函数的参数少于 4 个,该函数实际上也占有这 4 个堆栈位置,并可将这几个位置用于保存参数寄存器值以外的其他目的。 因此,在整个函数调用过程中,调用方不会将信息保存在此堆栈区域中。
少于4个参数的情况
00000013F441088 mov rdx,
000000013F44108D mov rcx,
000000013F441092 call @ILT+0(?xxx@@YA_J_J0@Z)函数内部:
000000013F441020 mov ,rdx
000000013F441025 mov ,rcx这样的话,如果已知函数参数已知,没必要从rsp去取参数了,少于5个的参数可以直接从寄存器得到
那么,传指针的情况呢?
#include <windows.h>
void xxx(INT64 a,INT64 b ,INT64 c,INT64 d,INT64 e,INT64 *p)
{
*p = a + b + c + d + e;
}
int _tmain(int argc, _TCHAR* argv[])
{
INT64 a,b,c,d,e;
INT64 x = 0;
scanf("%I64d %I64d %I64d %I64d %I64d",&a,&b,&c,&d,&e);
xxx(a,b,c,d,e,&x);
printf("%I64d\n",x);
return 0;
}000000013FE210D9 lea rax,
000000013FE210E1 mov ,rax
000000013FE210E6 mov rax,
000000013FE210EE mov ,rax
000000013FE210F3 mov r9,
000000013FE210FB mov r8,
000000013FE21100 mov rdx,
000000013FE21105 mov rcx,
000000013FE2110A call @ILT+0(?xxx@@YAX_J0000PEA_J@Z)
000000013FE2110F mov rdx,
传参方式不变。传入的 x在
取的时候还直接取
函数内部:
000000013FE21054 mov rcx,
000000013FE21059 mov ,rax那么,局部变量呢?#include <windows.h>
void xxx(INT64 a,INT64 b ,INT64 c,INT64 *p)
{
int d = 4;
int e = 5;
*p = a + b + c + d + e;
}
int _tmain(int argc, _TCHAR* argv[])
{
INT64 a,b,c;
INT64 x = 0;
scanf("%I64d %I64d %I64d",&a,&b,&c);
xxx(a,b,c,&x);
printf("%I64d\n",x);
return 0;
}永远不变的是先把rcx,rdx,r8,r9放到堆栈,然后sub esp,给局部变量腾空间
000000013F121020 mov ,r9
000000013F121025 mov ,r8
000000013F12102A mov ,rdx
000000013F12102F mov ,rcx
000000013F121034 push rdi
000000013F121035 sub rsp,0x10
000000013F121039 mov rdi,rsp
000000013F12103C mov ecx,0x4
000000013F121041 mov eax,0xCCCCCCCC
000000013F121046 rep stosd
000000013F121048 mov rcx,
000000013F12104D mov dword ptr ,0x4
000000013F121054 mov dword ptr ,0x5
膜拜大神…… 这个是否和编译优化有关系呢? 不错 有时间再试试浮点型数据传参 大大的惊喜 我来收藏了。谢谢zaas大侠 学习 看懂就可以调用64位未知DLL了 厉害,学到不少东西
页:
[1]