前篇分析过在objc中函数调用传参的一般方式,本篇分析vc在x64体系中的一般传参方式。手头上因为没有64位的vc编译器,只好用windbg看ms自身的函数是怎么样调用的。

首先看两个再熟悉不过的api,memset和CreateHeap。函数原型和使用像呼吸一样了,也不用多解释一看就明白。

调用memset(rcx, rdx, r8):

`76df5f63 488b842480000000 mov     rax,qword ptr [rsp+80h]
`76df5f6b mov qword ptr [rsp+98h],rax
`76df5f73 458bc5 mov r8d,r13d
`76df5f76 33d2 xor edx,edx
`76df5f78 488bc8 mov rcx,rax
`76df5f7b e810cfffff call ntdll!memset (`76df2e90)

调用RtlCreateHeap(rcx, rdx, r8, r9, [rsp+20h], [rsp+28h]):

`76de47a6 4c8b842498000000 mov     r8,qword ptr [rsp+98h]
`76de47ae 488d05ab200000 lea rax,[ntdll!RtlReleaseMemoryStream (`76de6860)]
`76de47b5 448d4e01 lea r9d,[rsi+]
`76de47b9 488bd7 mov rdx,rdi
`76de47bc mov qword ptr [rsp+188h],rax
`76de47c4 488d842440010000 lea rax,[rsp+140h]
`76de47cc b900800000 mov ecx,8000h
`76de47d1 mov qword ptr [rsp+28h],rax
`76de47d6 c784244001000060000000 mov dword ptr [rsp+140h],60h
`76de47e1 48c784247801000000100000 mov qword ptr [rsp+178h],1000h
`76de47ed mov qword ptr [rsp+20h],rsi
`76de47f2 4c89842480010000 mov qword ptr [rsp+180h],r8
`76de47fa e8a18cffff call ntdll!RtlCreateHeap (`76ddd4a0)

再来分析一下有多个参数的api函数。

`74a4b6f9 4c8d5c2450      lea     r11,[rsp+50h]
`74a4b6fe 488d442470 lea rax,[rsp+70h]
`74a4b703 4c895c2448 mov qword ptr [rsp+48h],r11
`74a4b708 mov qword ptr [rsp+40h],rax
`74a4b70d 488d842480000000 lea rax,[rsp+80h]
`74a4b715 mov qword ptr [rsp+38h],rax
`74a4b71a 488d842490000000 lea rax,[rsp+90h]
`74a4b722 4c8d8c24b0000000 lea r9,[rsp+0B0h]
`74a4b72a mov qword ptr [rsp+30h],rax
`74a4b72f 488d8424a0000000 lea rax,[rsp+0A0h]
`74a4b737 4c8d8424c0000000 lea r8,[rsp+0C0h]
`74a4b73f 488d542460 lea rdx,[rsp+60h]
`74a4b744 488d8c2400010000 lea rcx,[rsp+100h]
`74a4b74c 4c89742428 mov qword ptr [rsp+28h],r14
`74a4b751 mov qword ptr [rsp+20h],rax
`74a4b756 ff153c5affff call qword ptr [wow64+0x1198 (`74a41198)]

wow64经一些处理后跳转到ntdll!RtlCreateProcessParameters

ntdll!RtlCreateProcessParameters:
`76dede20 4883ec68 sub rsp,68h
`76dede24 488b8424b8000000 mov rax,qword ptr [rsp+0B8h]
`76dede2c c744245000000000 mov dword ptr [rsp+50h],
`76dede34 mov qword ptr [rsp+48h],rax
`76dede39 488b8424b0000000 mov rax,qword ptr [rsp+0B0h]
`76dede41 mov qword ptr [rsp+40h],rax
`76dede46 488b8424a8000000 mov rax,qword ptr [rsp+0A8h]
`76dede4e mov qword ptr [rsp+38h],rax
`76dede53 488b8424a0000000 mov rax,qword ptr [rsp+0A0h]
`76dede5b mov qword ptr [rsp+30h],rax
`76dede60 488b842498000000 mov rax,qword ptr [rsp+98h]
`76dede68 mov qword ptr [rsp+28h],rax
`76dede6d 488b842490000000 mov rax,qword ptr [rsp+90h]
`76dede75 mov qword ptr [rsp+20h],rax
`76dede7a e851b4feff call ntdll!RtlCreateProcessParametersEx (`76dd92d0)

RtlCreateProcessParameters函数将上一层传入的参数原封不动,并在后面增加一个参数0,然用后调RtlCreateProcessParametersEx。

RtlCreateProcessParameters函数一共有10个参数,RtlCreateProcessParametersEx函数一共有11个参数。
前4个参数使用的寄存器rcx,rdx,r8和r9, 后6个参数用了入栈方式,虽然前4个参数作用了寄存器,但仍然在堆栈中空出了4个qword的位置。第五个参数起是由rsp+20h处开始放入(mov)堆栈(,入栈push是由最后一个开始)。
线程在调用RtlCreateProcessParameters前,准备调用栈过程中并没有往rsp~rsp+18h处写东西,而从寄存器的调配可以看出用了寄存器rcx,rdx,r8,r9。
线程在调用RtlCreateProcessParametersEx前,将上一层调用栈后面6个参数搬运了过来,并增加了一个参数放到rsp+50h处。

通过windbg浏览几处api函数调用,可以看出vc的__stdcall调用的传参方式。前4个参数使用rcx,rdx,r8,r9,之后的参数使用堆栈并且在调用栈中空出4个qword位置,第5个参数不是rsp-8而是rsp-28h在函数入口处时。如果参数数量不超过4个,不使用堆栈。反汇编代码也说明vc在传参数时没有使用到rdi,rsi。

下一篇分析gcc在x64的传参方式。

上一篇分析objc在x64的传参方式。

vc在x64体系的一般传参数方式的更多相关文章

  1. gcc在x64体系中如何传递参数,linux,mac,iOS适用

    上一篇介绍了vc(windows)平台在x64体系当中,c函数的传参方式.本篇将要介绍gcc(类linux,mac)平台在x64中,c函数是如何传参的.为节约时间和篇幅,首先来定义一个有十个参数的函数 ...

  2. GET传参数方式

    controller:/getDetail/{id} /getDetail?id1234567 /getDetail?id=id1234567

  3. 超链接向servlet传参数

    超链接传参数方式如下: <a href=xxxServlet?flag=1  target=“XX”></a> 注意:target=“XX”是用来指定在什么窗体打开.xx为该窗 ...

  4. 传参数应该用哪种形式——值、引用、指针?

    类型:C++ & Qt4,创建时间:十二月 30, 2011, 7:43 p.m. 标题无"转载"即原创文章,版权所有.转载请注明来源:http://hgoldfish.c ...

  5. Mybatis传参数

    1使用@Param注解传参数 mapper接口:public void updateUser(@Param("user")User user)throws Exception; m ...

  6. 如何给main传参数

    main 函数的参数有连个argc argcv[]  argc 是参数个数 argcv是参数的数组指针,且argcv的第一个参数是默认程序路径加程序名 给main传参数,需要在命令行启动程序时设置 如 ...

  7. mvc中多参数URL会很长,首次加载不传参数让url很短,路由规则实现方法[bubuko.com]

    如要实现列表中地址全路径“bubuko-11-2.html”,在首次进入时,使用短路径“bubuko.html”,只有再次href后才显示全路径“bubuko-11-2.html”,下面使用路由规则来 ...

  8. Chrome和Firefox浏览器执行new Date() 函数传参数得到不同结果的陷阱

    某日,同事问到关于new Date() 函数传参数,在火狐浏览器和谷歌浏览器控制台运行,会得到不同的结果,刚开始觉得不可能,后来实际操作才发现此陷阱 var date = new Date('2014 ...

  9. web service上传参数代码实例

    web service上传参数代码实例 这次做的项目用到webservice比较多,最开始在网上看的参考dome,发现都不行,后来发现安卓4.0以后有很大的不同,在做传参时,有些东西需要注意: 第一, ...

随机推荐

  1. [七年技术总结系列][理论篇]-RBAC权限模型由浅入深

    权限部分将分两章介绍,第一章由浅入深介绍权限理论知识及应用,第二章介绍具体实现.后期再讲述中间件的使用时,还会插入一些权限内容,本质上属于中间件的应用. 权限模块是业务系统最常见.最基本的子集.本章假 ...

  2. C#的集合类型及使用技巧

    在日常开发过程中,我们不能避免的要对批量数据处理,这时候就要用到集合.集合总体上分为线性集合和非线性集合.线性集合是指元素具有唯一的前驱和后驱的数据结构类型:非线性集合是指有多个前驱和后驱的数据结构类 ...

  3. 快速排序方法——python实现

    参考博文:http://www.cnblogs.com/jingmoxukong/p/4302891.html 快速排序是一种交换排序. 快速排序由C. A. R. Hoare在1962年提出. 它的 ...

  4. js重点

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  5. SOLID原则、设计模式适用于Python语言吗

    在阅读 clean architecture的过程中,会发现作者经常提到recompile redeploy,这些术语看起来都跟静态类型语言有关,比如Java.C++.C#.而在我经常使用的pytho ...

  6. 汇编语言——物理地址=段地址x16+偏移地址,检测点2.2

    一.为什么 物理地址=段地址x16+偏移地址? 刚开始学时,我都笨到不明白为什么是2的N次方,咱把物理地址就当数字,计算机中数字是由很多位0或1自由组合的, 而每一位上要么是0要么是1,只有这两种情况 ...

  7. Python安装pyinstaller方法,以及将项目生成可执行程序的步骤

    pyinstaller安装方法 前提:确保计算机安装了Python语言环境,并且正确配置了环境变量. 方法一:联网在线自动安装 选择一 Windows OS下进入cmd(命令行窗口) 输入:pip i ...

  8. [考试反思]0810NOIP模拟测试16:黎明

    好吧,你尽力啦.我不说什么啦 []200 []180 [6]170 [7]160 [11]150 [12]140 还好,和前面的差距不大.虽说没有原来最好的那段时间考得那么好,但貌似还可以接受. 这次 ...

  9. ElasticSearch(四):基本搜索

    ElasticSearch(四):基本搜索 学习课程链接<Elasticsearch核心技术与实战> URI Search 使用HTTP的GET方法,在URL中使用查询参数进行查询. GE ...

  10. 爬虫学习--Day4(网页采集器的实现)

    #UA: User-Agent {请求载体的身份标识}#(反爬机制)UA检测:门户网站的服务器回检测对应请求的载体身份标识,如果检测到请求的载体身份为某一款浏览器就说明该请求时一个正常的请求.但是,如 ...