本帖最后由 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,[rsp+0x138]
- 000000013FDF114F mov [rsp+0x38],rax
- 000000013FDF1154 mov rax,[rsp+0x118]
- 000000013FDF115C mov [rsp+0x30],rax
- 000000013FDF1161 mov rax,[rsp+0xF8]
- 000000013FDF1169 mov [rsp+0x28],rax
- 000000013FDF116E mov rax,[rsp+0xD8]
- 000000013FDF1176 mov [rsp+0x20],rax
- 000000013FDF117B mov r9,[rsp+0xB8]
- 000000013FDF1183 mov r8,[rsp+0x98]
- 000000013FDF118B mov rdx,[rsp+0x78]
- 000000013FDF1190 mov rcx,[rsp+0x58]
- 000000013FDF1195 call @ILT+0(?xxx@@YA_J_J0000000@Z)
复制代码 rcx,rdx,r8,r9,[rsp+0x20],[rsp+0x28],[rsp+0x30],[rsp+0x38]
到函数里边:
- 00000013FDF1030 mov [rsp+0x20],r9
- 000000013FDF1035 mov [rsp+0x18],r8
- 000000013FDF103A mov [rsp+0x10],rdx
- 000000013FDF103F mov [rsp+0x8],rcx
复制代码 也就是说到函数里边,还是先把rcx,rdx,r8,r9放到堆栈对应的位置去。。。
即使被调用函数的参数少于 4 个,该函数实际上也占有这 4 个堆栈位置,并可将这几个位置用于保存参数寄存器值以外的其他目的。 因此,在整个函数调用过程中,调用方不会将信息保存在此堆栈区域中。
少于4个参数的情况
- 00000013F441088 mov rdx,[rsp+0x48]
- 000000013F44108D mov rcx,[rsp+0x28]
- 000000013F441092 call @ILT+0(?xxx@@YA_J_J0@Z)
复制代码 函数内部:
- 000000013F441020 mov [rsp+0x10],rdx
- 000000013F441025 mov [rsp+0x8],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,[rsp+0xD8]
- 000000013FE210E1 mov [rsp+0x28],rax
- 000000013FE210E6 mov rax,[rsp+0xB8]
- 000000013FE210EE mov [rsp+0x20],rax
- 000000013FE210F3 mov r9,[rsp+0x98]
- 000000013FE210FB mov r8,[rsp+0x78]
- 000000013FE21100 mov rdx,[rsp+0x58]
- 000000013FE21105 mov rcx,[rsp+0x38]
- 000000013FE2110A call @ILT+0(?xxx@@YAX_J0000PEA_J@Z)
- 000000013FE2110F mov rdx,[rsp+0xD8]
复制代码
传参方式不变。传入的 x在[rsp+0xD8]
取的时候还直接取[rsp+0xD8]
函数内部:
- 000000013FE21054 mov rcx,[rsp+0x38]
- 000000013FE21059 mov [rcx],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 [rsp+0x20],r9
- 000000013F121025 mov [rsp+0x18],r8
- 000000013F12102A mov [rsp+0x10],rdx
- 000000013F12102F mov [rsp+0x8],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,[rsp+0x20]
- 000000013F12104D mov dword ptr [rsp],0x4
- 000000013F121054 mov dword ptr [rsp+0x4],0x5
复制代码
|