上一篇 博文提到了 X64 下 MSVC 如何传递参数,但是没有涉及到当参数个数大于 4 的时候如何分配内存空间的问题,接下来我们来探究这个问题。

RSP 和 RBP

按照上面提到的博文,我们进行如下实验:

  1. 所有参数都是 struct Arg, 并且 sizeof(Arg) == 16
  2. 实验中,参数的个数 k = 6, 7, 8,先观察汇编后 rsprbp 寄存器的变化。

实验:
1. k = 6

; 28   : void Call() {$LN3:
00000   40 55        push    rbp
00002   56       push    rsi
00003   57       push    rdi
00004   48 81 ec f0 03
00 00        sub     rsp, 1008      ; 000003f0H
0000b   48 8d 6c 24 30   lea     rbp, QWORD PTR [rsp+48]
00010   48 8b fc     mov     rdi, rsp
  1. k = 7
; 28   : void Call() {
$LN3:00000   40 55        push    rbp00002   56       push    rsi00003   57       push    rdi00004   48 81 ec 60 0400 00        sub     rsp, 1120      ; 00000460H0000b   48 8d 6c 24 40   lea     rbp, QWORD PTR [rsp+64]00010   48 8b fc     mov     rdi, rsp
  1. k = 8
; 28   : void CallFuck() {$LN3:00000   40 55        push    rbp00002   56       push    rsi00003   57       push    rdi00004   48 81 ec c0 0400 00        sub     rsp, 1216      ; 000004c0H0000b   48 8d 6c 24 40   lea rbp, QWORD PTR [rsp+64]

这里我们需要明确一点,就是 rbp 的意义和 rsp 的意义是什么。
rbp 是属于当前函数的栈空间基地址,rsp 是包含当前函数为被调用函数准备的栈空间的基地址。

这点可以在汇编代码中看出来。

我们可以看出,当 k=6 的时候,MSVC 利用 lea rbp, QWORD PTR [rsp+48] 使得 rbp == rsp + 48
k = 7, 8 时 rbp == rsp + 64
根据 X64 下的传参规则,当 sizeof(struct) 不为 8, 16, 32, 64 bits 时,将指向参数本体的指针放在对应的位置,因此,一个参数(这里指这个指针,64 bits = 8 bytes)在栈上所占用的内存应该为 M = 8 * (#arg - 4)
所以, k = 6, M = 16; k = 7, M = 24; k = 8, M = 32; 再加上分配的 32 bytes 影子空间,那么应该是

k = 6, rbp == rsp + 48
k = 7, rbp == rsp + 56
k = 8, rbp == rsp + 64·

实际情况呢,k = 7 我们和编译器结果不一样,实际情况是 rbp == rsp + 64,原因在于

为这些聚合类型作为指针的传递 (包括__m128),调用方分配的临时内存将是 16 字节对齐。

因此这些指针虽然单个大小是 8,所以在奇数个的时候为了对齐要额外增加 8 !

Calling Convention

根据这个简单的调用约定,我们可以画出64位下函数调用时到底是个怎么样的内存结构。(时机应该是 call 指令执行完毕)

这张图片认真理解,就解决了所有调用时对于内存空间如何分配的疑问。

See also:

https://docs.microsoft.com/zh-cn/cpp/build/stack-allocation

本篇基于实验得出,除了某些叫法不同,和微软的官方文档是一致的。

MSVC X64 函数中的 RSP, RBP 和 Calling Convention相关推荐

  1. 函数的隐式声明 及 rsp,rbp,被调用者和调用者保存的寄存器standerd manuel(Caller/Callee - saved registers)

    函数的隐式声明 https://blog.csdn.net/liangbo930522/article/details/73733415 mpx-linux64-abi.pdf https://sof ...

  2. rsp rbp 寄存器用途

    概念 在最新的 x86_x64 架构中,通常用 rbp.rsp 这两个寄存器来保存进程栈的状态(需要硬件支持). 其中 rbp 保存的是栈中当前执行函数的基本地址,当前执行函数所有存储在栈上的数据都要 ...

  3. C#利用lambda在函数中创建内部函数

    有使用过JS的朋友,相信都知道function.JS中的function是可以在里面在定义一个作为内部使用的.有时为了控制作用域,或者这种小函数只在这个函数体内会使用,所以就不希望在外部在作额外的定义 ...

  4. 在c语言中,函数中的自动变量可以赋初值,每调用一次,赋一次初值,计算机二级考试 程序设计基础试题及答案三...

    <程序设计基础>考试试卷三 1. 判断下面标识符中哪个是C语言中合法的用户定义标识符: A. a-b B. #abd C. typedef D. _max 2. -b?在内存中占个字节,& ...

  5. c语言实验至少包括四个函数中,C语言实验报告《函数》

    学号:__________    姓名:__________    班级:__________    日期:__________ 指导教师:__________    成绩:__________ 实验 ...

  6. java用if语句调用方法_J2SE中main函数中的if语句想要调用另一个类的方法怎么能实现?...

    日常生活中,要完成一件复杂的功能,我们总是习惯把"大功能"分解为多个"小功能"以实现.在C++程序的世界里,"功能"可称呼为"函数 ...

  7. ACMNO.41C语言-数字调序 有n个整数,使前面各数顺序向后移m个位置,最后m个数变成前面m个数,见图。写一函数:实现以上功能,在主函数中输入n个数和输出调整后的n个数

    题目描述 有n个整数,使前面各数顺序向后移m个位置,最后m个数变成前面m个数,见图. 写一函数:实现以上功能,在主函数中输入n个数和输出调整后的n个数. 输入 输入数据的个数n n个整数 移动的位置m ...

  8. ACMNO.27 Python的两行代码解决 C语言-字符逆序 写一函数。使输入的一个字符串按反序存放,在主函数中输入输出反序后的字符串。 输入 一行字符 输出 逆序后的字符串

    题目描述 写一函数,使输入的一个字符串按反序存放,在主函数中输入输出反序后的字符串. 输入 一行字符 输出 逆序后的字符串 样例输入 123456abcdef 样例输出 fedcba654321 来源 ...

  9. ACMNO.26 C语言-字符统计2 编写一函数,由实参传来一个字符串,统计此字符串中字母、数字、空格和其它字符的个数,在主函数中输入字符串以及输出上述结果。 只要结果,别输出什么提示信息。

    题目描述 编写一函数,由实参传来一个字符串,统计此字符串中字母.数字.空格和其它字符的个数, 在主函数中输入字符串以及输出上述结果. 只要结果,别输出什么提示信息. 输入 一行字符串 输出 统计数据, ...

最新文章

  1. Self Ogannizing Maps(SOM)自组织映射
  2. golang重复声明变量
  3. 非监督HMP算法的物体识别
  4. SQL Server 监控统计阻塞脚本信息
  5. java 连接linux失败,Jenkins连接Linux失败
  6. 【渝粤题库】国家开放大学2021春1070组织行为学题目
  7. GCC笔记 命令行分析
  8. ZXing生成二维码
  9. C++新特性探究(18.2):C++11 unique_ptr智能指针详解
  10. 我和Django那些事儿(8)----相册django插件photologue,jQuery插件Slides
  11. redis 集群_Redis集群部署
  12. 五分钟带你玩转rabbitmq(八)【真实案例】消息消费失败如何处理?
  13. 计算机无法启动怎么重装系统,韩博士教你如何为系统崩溃无法开机的电脑重装系统...
  14. 如何用美剧真正提升你的英语水平?
  15. 【排序算法】基数排序:LSD 与 MSD
  16. matlab含未知数矩阵方程组,solve函数求解含有未知数的矩阵方程问题
  17. linux查找文件中的字符串
  18. DRAG DROP
  19. 几种常见的软件授权模式
  20. Groups CodeForces - 1598B

热门文章

  1. 终于放假咯~寒假规划
  2. API调用,淘宝天猫、1688、京东、拼多多商品页面APP端原数据获取
  3. 【独家】寒武纪A轮融资1亿美元,成全球AI芯片首个独角兽,阿里参投
  4. 网页上播放微信录音amr文件方案
  5. 手写经典游戏 - FlappyBird
  6. Html 后端了解基础
  7. Linux ffs()函数
  8. 电脑麦克风没声音怎么办?3个方法快速解决
  9. Chapter8.金融时间序列
  10. 鼠标手是否算工伤 专家:法定职业病才能获赔