飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 8115|回复: 6

[x64] x64 传参再分析

[复制链接]
  • TA的每日心情
    无聊
    2024-1-15 22:57
  • 签到天数: 3 天

    [LV.2]偶尔看看I

    发表于 2014-11-6 21:23:51 | 显示全部楼层 |阅读模式
    本帖最后由 zaas 于 2014-11-6 21:51 编辑

    老飘写的还有一点没看懂:为啥第五个参数从rsp + 20开始??自己写代码测试下:
    1. #include <windows.h>

    2. INT64 xxx(INT64 a,INT64 b ,INT64 c,INT64 d,INT64 e,INT64 f,INT64 g,INT64 h)
    3. {
    4.         return a + b + c + d + e + f + g + h;

    5. }

    6. int yyy(int a,int b ,int c,int d,int e,int f,int g,int h)
    7. {
    8.         return a + b + c + d + e + f + g + h;
    9. }

    10. int _tmain(int argc, _TCHAR* argv[])
    11. {
    12.         INT64 a,b,c,d,e,f,g,h;
    13.         int p,q,r,s,t,u,v,w;

    14.         scanf("%I64d %I64d %I64d %I64d %I64d %I64d %I64d %I64d",&a,&b,&c,&d,&e,&f,&g,&h);
    15.         printf("%I64d\n",xxx(a,b,c,d,e,f,g,h));
    16.         fflush(stdin);
    17.         scanf("%d %d %d %d %d %d %d %d",&p,&q,&r,&s,&t,&u,&v,&w);
    18.         printf("%d\n",yyy(p,q,r,s,t,u,v,w));
    19.         return 0;
    20. }
    复制代码
    传参:


    1. 000000013FDF1147   mov         rax,[rsp+0x138]
    2. 000000013FDF114F   mov         [rsp+0x38],rax
    3. 000000013FDF1154   mov         rax,[rsp+0x118]
    4. 000000013FDF115C   mov         [rsp+0x30],rax
    5. 000000013FDF1161   mov         rax,[rsp+0xF8]
    6. 000000013FDF1169   mov         [rsp+0x28],rax
    7. 000000013FDF116E   mov         rax,[rsp+0xD8]
    8. 000000013FDF1176   mov         [rsp+0x20],rax
    9. 000000013FDF117B   mov         r9,[rsp+0xB8]
    10. 000000013FDF1183   mov         r8,[rsp+0x98]
    11. 000000013FDF118B   mov         rdx,[rsp+0x78]
    12. 000000013FDF1190   mov         rcx,[rsp+0x58]
    13. 000000013FDF1195   call        @ILT+0(?xxx@@YA_J_J0000000@Z)
    复制代码
    rcx,rdx,r8,r9,[rsp+0x20],[rsp+0x28],[rsp+0x30],[rsp+0x38]
    到函数里边:
    1. 00000013FDF1030   mov         [rsp+0x20],r9
    2. 000000013FDF1035   mov         [rsp+0x18],r8
    3. 000000013FDF103A   mov         [rsp+0x10],rdx
    4. 000000013FDF103F   mov         [rsp+0x8],rcx
    复制代码
    也就是说到函数里边,还是先把rcx,rdx,r8,r9放到堆栈对应的位置去。。。
    即使被调用函数的参数少于 4 个,该函数实际上也占有这 4 个堆栈位置,并可将这几个位置用于保存参数寄存器值以外的其他目的。 因此,在整个函数调用过程中,调用方不会将信息保存在此堆栈区域中。

    少于4个参数的情况
    1. 00000013F441088   mov         rdx,[rsp+0x48]
    2. 000000013F44108D   mov         rcx,[rsp+0x28]
    3. 000000013F441092   call        @ILT+0(?xxx@@YA_J_J0@Z)
    复制代码
    函数内部:
    1. 000000013F441020   mov         [rsp+0x10],rdx
    2. 000000013F441025   mov         [rsp+0x8],rcx
    复制代码
    这样的话,如果已知函数参数已知,没必要从rsp去取参数了,少于5个的参数可以直接从寄存器得到

    那么,传指针的情况呢?
    1. #include <windows.h>

    2. void xxx(INT64 a,INT64 b ,INT64 c,INT64 d,INT64 e,INT64 *p)
    3. {
    4.                 *p = a + b + c + d + e;
    5. }

    6. int _tmain(int argc, _TCHAR* argv[])
    7. {
    8.         INT64 a,b,c,d,e;
    9.         INT64 x = 0;        

    10.         scanf("%I64d %I64d %I64d %I64d %I64d",&a,&b,&c,&d,&e);
    11.         xxx(a,b,c,d,e,&x);
    12.         printf("%I64d\n",x);

    13.         return 0;
    14. }
    复制代码
    1. 000000013FE210D9   lea         rax,[rsp+0xD8]
    2. 000000013FE210E1   mov         [rsp+0x28],rax
    3. 000000013FE210E6   mov         rax,[rsp+0xB8]
    4. 000000013FE210EE   mov         [rsp+0x20],rax
    5. 000000013FE210F3   mov         r9,[rsp+0x98]
    6. 000000013FE210FB   mov         r8,[rsp+0x78]
    7. 000000013FE21100   mov         rdx,[rsp+0x58]
    8. 000000013FE21105   mov         rcx,[rsp+0x38]
    9. 000000013FE2110A   call        @ILT+0(?xxx@@YAX_J0000PEA_J@Z)
    10. 000000013FE2110F   mov         rdx,[rsp+0xD8]
    复制代码

    传参方式不变。传入的 x在[rsp+0xD8]
    取的时候还直接取[rsp+0xD8]
    函数内部:
    1. 000000013FE21054   mov         rcx,[rsp+0x38]
    2. 000000013FE21059   mov         [rcx],rax
    复制代码
    那么,局部变量呢?
    1. #include <windows.h>

    2. void xxx(INT64 a,INT64 b ,INT64 c,INT64 *p)
    3. {
    4.                 int d = 4;
    5.                 int e = 5;
    6.                 *p = a + b + c + d + e;
    7. }

    8. int _tmain(int argc, _TCHAR* argv[])
    9. {
    10.         INT64 a,b,c;
    11.         INT64 x = 0;       

    12.         scanf("%I64d %I64d %I64d",&a,&b,&c);
    13.         xxx(a,b,c,&x);
    14.         printf("%I64d\n",x);

    15.         return 0;
    16. }
    复制代码
    永远不变的是先把rcx,rdx,r8,r9放到堆栈,然后sub esp,给局部变量腾空间
    1. 000000013F121020   mov         [rsp+0x20],r9
    2. 000000013F121025   mov         [rsp+0x18],r8
    3. 000000013F12102A   mov         [rsp+0x10],rdx
    4. 000000013F12102F   mov         [rsp+0x8],rcx
    5. 000000013F121034   push        rdi
    6. 000000013F121035   sub         rsp,0x10
    7. 000000013F121039   mov         rdi,rsp
    8. 000000013F12103C   mov         ecx,0x4
    9. 000000013F121041   mov         eax,0xCCCCCCCC
    10. 000000013F121046   rep stosd   
    11. 000000013F121048   mov         rcx,[rsp+0x20]
    12. 000000013F12104D   mov         dword ptr [rsp],0x4
    13. 000000013F121054   mov         dword ptr [rsp+0x4],0x5
    复制代码


    评分

    参与人数 4威望 +40 飘云币 +40 收起 理由
    2402436533 + 20 + 20 PYG有你更精彩!
    GeekCat + 8 + 8 赞一个!
    small-q + 8 + 8 很给力!
    vipcrack + 4 + 4 赞一个!

    查看全部评分

    PYG19周年生日快乐!
  • TA的每日心情
    开心
    2018-9-27 19:17
  • 签到天数: 31 天

    [LV.5]常住居民I

    发表于 2014-11-7 02:20:02 | 显示全部楼层
    这个是否和编译优化有关系呢?
    PYG19周年生日快乐!

    该用户从未签到

    发表于 2014-11-7 09:52:02 | 显示全部楼层
    不错 有时间再试试浮点型数据传参 大大的惊喜
    PYG19周年生日快乐!
  • TA的每日心情
    难过
    2024-3-10 19:49
  • 签到天数: 473 天

    [LV.9]以坛为家II

    发表于 2014-11-7 14:09:39 | 显示全部楼层
    我来收藏了。谢谢zaas大侠
    PYG19周年生日快乐!
  • TA的每日心情
    开心
    2019-6-13 21:25
  • 签到天数: 38 天

    [LV.5]常住居民I

    发表于 2014-11-7 18:49:14 | 显示全部楼层
    学习 看懂就可以调用64位未知DLL了
    PYG19周年生日快乐!
  • TA的每日心情
    开心
    2015-8-2 16:07
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-11-8 18:22:05 | 显示全部楼层
    厉害,学到不少东西
    PYG19周年生日快乐!
    您需要登录后才可以回帖 登录 | 加入我们

    本版积分规则

    快速回复 返回顶部 返回列表