__cdecl 调用约定不适用于 msvc x64

2024-02-01

只是一个测试__cdecl调用约定。

这是一个 cmake 项目,只有 1 个源文件:

#include <stdio.h>

#define CALL_CONVENTION __cdecl

void CALL_CONVENTION f(int a, int b)
{
    printf("%d, %d", a, b);
}

int main()
{
    f(1, 2);

    return 0;
}

我在用着set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /FA")输出汇编代码。

当我用cmake -G "Visual Studio 15",它正在构建一个 32 位应用程序,一切都在预料之中:

...
; Line 12
    push    ebp
    mov ebp, esp
; Line 13
    push    2        ; <------- argument 2
    push    1        ; <------- argument 1
    call    _f       ; <------- call function
    add esp, 8
; Line 15
    xor eax, eax
; Line 16
    cmp ebp, esp
    call    __RTC_CheckEsp
    pop ebp
    ret 0
_main   ENDP
...

你可以看到参数被传递了push 2 and push 1说明,它是__cdecl调用约定。

但如果我使用cmake -G "Visual Studio 15 Win64"要构建 64 位应用程序,__cdecl注释似乎不起作用(参数未通过堆栈传递):

...
; Line 12
$LN3:
    push    rdi
    sub rsp, 32                 ; 00000020H
    mov rdi, rsp
    mov ecx, 8
    mov eax, -858993460             ; ccccccccH
    rep stosd
; Line 13
    mov edx, 2        ; <------ argument 2
    mov ecx, 1        ; <------ argument 1
    call    f         ; <------ call function
; Line 15
    xor eax, eax
; Line 16
    add rsp, 32                 ; 00000020H
    pop rdi
    ret 0
main    ENDP
...

参数通过寄存器传递edx and ecx,不通过堆栈传递。

那么为什么即使我指定,参数在 x64 中也不会通过堆栈传递__cdecl如果我想在 x64 环境中做同样的事情我应该做什么。


x64 有它自己的调用约定。

微软文档__cdecl https://learn.microsoft.com/en-us/cpp/cpp/cdecl?view=vs-2019

在 ARM 和 x64 处理器上,__cdecl 被接受,但通常被编译器忽略。按照 ARM 和 x64 上的约定,如果可能,参数将在寄存器中传递,后续参数将在堆栈上传递。在 x64 代码中,使用 __cdecl 覆盖 /Gv 编译器选项并使用默认的 x64 调用约定。

Microsoft docs x64 calling convention https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention?view=vs-2019

默认情况下,x64 应用程序二进制接口 (ABI) 使用四寄存器快速调用约定。在调用堆栈上分配空间作为被调用者保存这些寄存器的影子存储。函数调用的参数与用于这些参数的寄存器之间存在严格的一一对应关系。任何不能容纳 8 个字节或不是 1、2、4 或 8 个字节的参数都必须通过引用传递。

...

整数参数在寄存器 RCX、RDX、R8 和 R9 中传递

您可以使用 ECX 和 EDX 来查看它int a and int b(因为它们是 32 位,而完整的 RAX 和 RDX 是 64 位)。

__stdcall https://learn.microsoft.com/en-us/cpp/cpp/stdcall?view=vs-2019, __fastcall https://learn.microsoft.com/en-us/cpp/cpp/fastcall?view=vs-2019 and __thiscall https://learn.microsoft.com/en-us/cpp/cpp/thiscall?view=vs-2019也被忽略。__vectorcall https://learn.microsoft.com/en-us/cpp/cpp/vectorcall?view=vs-2019可用(/Gv 开关使其成为默认值),并且是另一种寄存器调用约定,但与 x64 默认值相比,它可以在更多情况下使用寄存器,并且有一些其他规则差异。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

__cdecl 调用约定不适用于 msvc x64 的相关文章

  • 在 xaml 中编写嵌套类型时出现设计时错误

    我创建了一个用户控件 它接受枚举类型并将该枚举的值分配给该用户控件中的 ComboBox 控件 很简单 我在数据模板中使用此用户控件 当出现嵌套类型时 问题就来了 我使用这个符号来指定 EnumType x Type myNamespace
  • 自定义波特率,redux

    我遇到的问题详述如下自定义波特率 https stackoverflow com questions 7714060 custom baud rate SetCommState 波特率 921600 失败 但波特率 115200 成功 尽管
  • C++11 删除重写方法

    Preface 这是一个关于最佳实践的问题 涉及 C 11 中引入的删除运算符的新含义 当应用于覆盖继承父类的虚拟方法的子类时 背景 根据标准 引用的第一个用例是明确禁止调用某些类型的函数 否则转换将是隐式的 例如最新版本第 8 4 3 节
  • std::vector 与 std::stack

    有什么区别std vector and std stack 显然 向量可以删除集合中的项目 尽管比列表慢得多 而堆栈被构建为仅后进先出的集合 然而 堆栈对于最终物品操作是否更快 它是链表还是动态重新分配的数组 我找不到关于堆栈的太多信息 但
  • 传递给函数时多维数组的指针类型是什么? [复制]

    这个问题在这里已经有答案了 我在大学课堂上学习了 C 语言和指针 除了多维数组和指针之间的相似性之外 我认为我已经很好地掌握了这个概念 我认为由于所有数组 甚至多维 都存储在连续内存中 因此您可以安全地将其转换为int 假设给定的数组是in
  • 从经典 ASP 调用 .Net C# DLL 方法

    我正在开发一个经典的 asp 项目 该项目需要将字符串发送到 DLL DLL 会将其序列化并发送到 Zebra 热敏打印机 我已经构建了我的 DLL 并使用它注册了regasm其次是 代码库这使得 IIS 能够识别它 虽然我可以设置我的对象
  • Qt 支持 Windows 蓝牙 API 吗?

    谁能告诉我 Qt 是否支持 Windows 蓝牙 API 如果是这样 您能否分享一些有关如何使用它的信息 自上次答复以来 这个问题的答案发生了一些变化 Qt 5 2 版为 Linux BlueZ 和 BlackBerry 设备实现了蓝牙 A
  • C++ 多行字符串原始文字[重复]

    这个问题在这里已经有答案了 我们可以像这样定义一个多行字符串 const char text1 part 1 part 2 part 3 part 4 const char text2 part 1 part 2 part 3 part 4
  • C# 列表通用扩展方法与非通用扩展方法

    这是一个简单的问题 我希望 集合类中有通用和非通用方法 例如List
  • 在 Unity 中实现 Fur with Shells 技术

    我正在尝试在 Unity 中实现皮毛贝壳技术 http developer download nvidia com SDK 10 5 direct3d Source Fur doc FurShellsAndFins pdf Fins 技术被
  • 使用 C# 中的 CsvHelper 将不同文化的 csv 解析为十进制

    C 中 CsvHelper 解析小数的问题 我创建了一个从 byte 而不是文件获取 csv 文件的类 并且它工作正常 public static List
  • 为什么这个字符串用AesCryptoServiceProvider第二次解密时不相等?

    我在 C VS2012 NET 4 5 中的文本加密和解密方面遇到问题 具体来说 当我加密并随后解密字符串时 输出与输入不同 然而 奇怪的是 如果我复制加密的输出并将其硬编码为字符串文字 解密就会起作用 以下代码示例说明了该问题 我究竟做错
  • C# xml序列化必填字段

    我需要将一些字段标记为需要写入 XML 文件 但没有成功 我有一个包含约 30 个属性的配置类 这就是为什么我不能像这样封装所有属性 public string SomeProp get return someProp set if som
  • 实例化类时重写虚拟方法

    我有一个带有一些虚函数的类 让我们假设这是其中之一 public class AClassWhatever protected virtual string DoAThingToAString string inputString retu
  • 如何在 Linq to SQL 中使用distinct 和 group by

    我正在尝试将以下 sql 转换为 Linq 2 SQL select groupId count distinct userId from processroundissueinstance group by groupId 这是我的代码
  • 如何在 Android 中使用 C# 生成的 RSA 公钥?

    我想在无法假定 HTTPS 可用的情况下确保 Android 应用程序和 C ASP NET 服务器之间的消息隐私 我想使用 RSA 来加密 Android 设备首次联系服务器时传输的对称密钥 RSA密钥对已在服务器上生成 私钥保存在服务器
  • MySQL Connector C/C API - 使用特殊字符进行查询

    我是一个 C 程序 我有一个接受域名参数的函数 void db domains query char name 使用 mysql query 我测试数据库中是否存在域名 如果不是这种情况 我插入新域名 char query 400 spri
  • 类型或命名空间“MyNamespace”不存在等

    我有通常的类型或命名空间名称不存在错误 除了我引用了程序集 using 语句没有显示为不正确 并且我引用的类是公共的 事实上 我在不同的解决方案中引用并使用相同的程序集来执行相同的操作 并且效果很好 顺便说一句 这是VS2010 有人有什么
  • 现代编译器是否优化乘以 1 和 -1

    如果我写 template
  • 使用 WGL 创建现代 OpenGL 上下文?

    我正在尝试使用 Windows 函数创建 OpenGL 上下文 现代版本 基本上代码就是 创建窗口类 注册班级 创建一个窗口 choose PIXELFORMATDESCRIPTOR并设置它 创建旧版 OpenGL 上下文 使上下文成为当前

随机推荐

  • 视口单位 vw/vh/vmin/vmax 不支持缩放吗?

    As per 如何正确使用 css values viewport relative lengths https stackoverflow com questions 30175730 how to properly use css va
  • 将 Redis Streams 输出转换为 Pandas Dataframe

    会是什么fastest方法来转换一个Redis流 https redis io topics streams intro输出 aioredis 客户端 hiredis 解析器 到 Pandas Dataframe 其中 Redis 流 ID
  • 如何在 OS X 上重新启动 nginx

    我在用着nginx在 OS X 10 8 上 全新安装nginx但找不到重新启动 nginx 的方法 除了kill nginx pid say kill 64116 想知道是否有更好的重启方法nginx 在Google和SO上找到了一些方法
  • iPhone 使用证书加密

    我必须加密一个字符串 并在 xCode 项目的 Resources 文件夹中有一个 CER x 509 这两天我一直在想怎么做 但没有成功 所以是时候问一下了 Apple 的文档非常难以阅读 而且我认为这个框架可能是最难理解的框架 两个示例
  • React-ui-tree 对触摸设备的拖放支持

    我正在尝试为支持触摸的设备添加 DnD 支持反应 ui 树 https github com pqx react ui tree它的行为似乎很奇怪 虽然拖动似乎开始于触摸移动事件并突然停止 但如果你从同一个位置拾取并移动 那么事情似乎就会起
  • Java正则表达式以逗号分隔但忽略注释内的逗号

    我需要正则表达式用逗号 分割字符串 但忽略注释部分中的逗号 更改你的正则表达式后我尝试了很多 但没有成功 例如 Command RTRV EQPT Completion Code DENY Error Code II AC Problem
  • SQL Server:使用元组 IN 子句进行多重连接

    我正在尝试连接 4 个具有复杂关系的表 由于要使用它的位置 它需要包含在单个查询中 但我遇到了麻烦 因为主查询和 IN 子句查询都将 2 个表连接在一起 并且查找是在两列上进行的 目标是输入一个SalesNum and SalesType并
  • 使用 pygame.transform.rotate 时内存不足

    我写了一个脚本 允许用户控制老鹰的精灵飞来飞去以学习pygame 看起来很好 直到我实现了一个旋转函数 使精灵根据其飞行方向旋转 移动一小会儿后 精灵变得非常模糊 很快就会弹出一个错误 内存不足 在这一行 eagle img pygame
  • NullPointerException 但编译?

    我正在编写一个简单的命令行游戏 我已经有很多功能了 这里只发布必要的功能 问题 程序可以编译 但是当levelup 被呼叫并选择了一个号码 我得到这个 You have 5 skill points to spend What would
  • 实体子类的专用缓存区域?

    我们拥有一个包含 100 多个实体类的广泛实体模型 所有实体类都是单个实体超类的子类 共享缓存模式已设置为ALL Entity Inheritance strategy InheritanceType JOINED Table name e
  • 这是什么意思: qq = qq || {}? [复制]

    这个问题在这里已经有答案了 我已经下载了一个 JavaScript 脚本 第一行是 qq qq 这是什么意思 它检查qq对于预先存在的真实值 http 11heavens com falsy and truthy in javascript
  • 安装私有 Go 模块:未知修订错误

    我有一个私人 Go 存储库 位于https github com myorg myrepo被另一个 Go 存储库使用并定义在go mod 当我尝试跑步时 go mod tidy下载所有依赖项 它返回以下错误 go github com my
  • 处理400后运行时错误

    设想 用户名和密码使用 WebApi 2 令牌身份验证进行身份验证 如果凭据正确 则返回令牌 但是 如果凭据不正确 则会返回 400 bad request 在我的 Ionic 2 项目中 如果收到响应 我会导航到下一页 如果收到错误 我会
  • Java中使用Selenium快速获取每个WebElement的类属性

    我正在寻找每个的类属性WebElement用硒快速在页面上 目前 我正在执行以下操作 allElements new ArrayList
  • 当 setLabelsClipped 为 true 时,顶点标签在顶点外部、滚动条上和其他组件上绘制

    我使用 JGraph 一段时间了 当您将标签裁剪设置为 true 时 似乎存在绘画问题 下面的简化示例显示了您可能会遇到的实际应用程序中的问题 import java awt BorderLayout import java awt Dim
  • 在 MATLAB 中处理大型 CSV 文件

    我必须处理一个最大 2GB 的大 CSV 文件 更具体地说 我必须将所有这些数据上传到 mySQL 数据库 但在我必须对此进行一些计算之前 所以我需要在 MATLAB 中完成所有这些操作 我的主管也想在 MATLAB 中完成 因为他熟悉MA
  • 将嵌套 XML 数据与数据库表结构进行匹配的最快方法

    我有一个创建的应用程序datarequests这可能相当复杂 这些需要作为表存储在数据库中 一个轮廓datarequest 作为 XML 将是
  • 无法解析 MatDialogRef 角度 4 的所有参数

    我正在研究 Angular 4 我正在尝试设置材质包 在这里我尝试尝试对话框 但它不起作用 可能是因为我不确定材质包 这是我的 dialog components ts import Component OnInit from angula
  • NET::ERR_CERT_COMMON_NAME_INVALID - 错误消息

    前段时间我用 Flask 建立了一个网站 现在突然间 当我尝试导航到那里时 我得到以下信息 NET ERR CERT COMMON NAME INVALID 你的连接不是私人的 攻击者可能试图从 www mysite org 窃取您的信息
  • __cdecl 调用约定不适用于 msvc x64

    只是一个测试 cdecl调用约定 这是一个 cmake 项目 只有 1 个源文件 include