GCC 内联汇编:约束

2024-01-18

我很难理解 GCC 内联汇编 (x86) 中的角色约束。我有阅读手册 http://gcc.gnu.org/onlinedocs/gcc/Constraints.html#Constraints,它准确地解释了每个约束的作用。问题是,尽管我了解每个约束的作用,但我对为什么要使用一个约束而不是另一个约束,或者可能的含义知之甚少。

我意识到这是一个非常广泛的主题,所以一个小例子应该有助于缩小焦点。以下是一个简单的 asm 例程,仅将两个数字相加。如果发生整数溢出,则写入一个值1到输出 C 变量。

 int32_t a = 10, b = 5;
 int32_t c = 0; // overflow flag

 __asm__
 (
  "addl %2,%3;"        // Do a + b (the result goes into b)
  "jno 0f;"            // Jump ahead if an overflow occurred
  "movl $1, %1;"       // Copy 1 into c
  "0:"                 // We're done.

  :"=r"(b), "=m"(c)    // Output list
  :"r"(a), "0"(b)     // Input list
 );

现在这工作得很好,除了我必须任意摆弄约束,直到它正常工作为止。最初,我使用了以下约束:

  :"=r"(b), "=m"(c)    // Output list
  :"r"(a), "m"(b)     // Input list

请注意,我使用“m”约束代替“0”b。这有一个奇怪的副作用,如果我使用优化标志进行编译并调用该函数两次,由于某种原因,加法操作的结果也会存储在c。我最终读到了“匹配约束 http://www.ibm.com/developerworks/library/l-ia.html”,它允许您指定一个变量既用作输入操作数又用作输出操作数。当我更改时"m"(b) to "0"(b)有效。

但我真的不明白为什么你会使用一个约束而不是另一个。我的意思是,是的,我明白“r”意味着变量应该在寄存器中,“m”意味着它应该在内存中 - 但我不知道really了解选择一个而不是另一个的含义是什么,或者如果我选择某种约束组合,为什么加法运算无法正常工作。

问题: 1)在上面的示例代码中,为什么“m”约束对b cause c写信给? 2)是否有任何教程或在线资源可以更详细地介绍约束?


这是一个例子,可以更好地说明为什么您应该仔细选择约束(与您的函数相同,但可能写得更简洁):

bool add_and_check_overflow(int32_t& a, int32_t b)
{
    bool result;
    __asm__("addl %2, %1; seto %b0"
            : "=q" (result), "+g" (a)
            : "r" (b));
    return result;
}

因此,使用的约束是:q, r, and g.

  • q仅仅意味着eax, ecx, edx, or ebx可以选择。这是因为set*指令必须写入 8 位可寻址寄存器(al, ah,...)。指某东西的用途b in the %b0意味着,使用最低 8 位部分(al, cl, ...).
  • 对于大多数双操作数指令,至少其中一个操作数必须是寄存器。所以不要使用m or g对彼此而言;使用r对于至少一个操作数。
  • 对于最终的操作数,无论是寄存器还是内存都没有关系,所以使用g(一般的)。

在上面的例子中,我选择使用g(而不是r) for a因为引用通常被实现为内存指针,所以使用r约束需要首先将引用对象复制到寄存器,然后再复制回来。使用g,可以直接更新参考对象。


至于为什么你的原始版本覆盖了你的c与加法的值,那是因为你指定=m在输出槽中,而不是(比如说)+m;这意味着编译器可以重复使用相同的内存位置进行输入和输出。

在你的情况下,这意味着两种结果(因为相同的内存位置被用于b and c):

  • 添加没有溢出:那么,c被值覆盖b(相加的结果)。
  • 加法确实溢出了:那么,c变成 1(并且b也可能变成 1,具体取决于代码的生成方式)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

GCC 内联汇编:约束 的相关文章

  • 使用 std::packaged_task/std::exception_ptr 时,线程清理程序报告数据争用

    我遇到了线程清理程序 TSan 的一些问题 抱怨某些生产代码中的数据争用 其中 std packaged task 通过将它们包装在 std function 中而移交给调度程序线程 对于这个问题 我简化了它在生产中的作用 同时触发 TSa
  • 未提供参数时如何指定 C# System.Commandline 行为?

    在我的控制台应用程序中 当未提供控制台参数时 将执行我指定列表 在本例中为参数 3 的任何处理程序 调用该处理程序时 布尔参数设置为 false 但对我来说 根本不调用它更有意义 如何防止这种情况发生并显示帮助文本 using System
  • 注销租约抛出 InvalidOperationException

    我有一个使用插件的应用程序 我在另一个应用程序域中加载插件 我使用 RemoteHandle 类http www pocketsilicon com post Things That Make My Life Hell Part 1 App
  • 为什么 int8_t 和用户通过 cin 输入显示奇怪的结果[重复]

    这个问题在这里已经有答案了 一小段代码让我发疯 但希望你能阻止我跳出窗外 看这里 include
  • 计算 Richtextbox 中所有单词的最有效方法是什么?

    我正在编写一个文本编辑器 需要提供实时字数统计 现在我正在使用这个扩展方法 public static int WordCount this string s s s TrimEnd if String IsNullOrEmpty s re
  • 提交后禁用按钮

    当用户提交付款表单并且发布表单的代码导致 Firefox 中出现重复发布时 我试图禁用按钮 去掉代码就不会出现这个问题 在firefox以外的任何浏览器中也不会出现这个问题 知道如何防止双重帖子吗 System Text StringBui
  • C中的malloc内存分配方案

    我在 C 中尝试使用 malloc 发现 malloc 在分配了一些内存后浪费了一些空间 下面是我用来测试 malloc 的一段代码 include
  • 在 LINQ 中按 Id 连接多表和分组

    我想按categoryId显示列表产品的名称组 这是我的代码 我想要我的视图显示结果 Desktop PC HP Red PC Dell Yellow PC Asus Red SmartPhone Lumia 720 Blue 我的组模型
  • 使用 LINQ2SQL 在 ASP.NET MVC 中的各种模型存储库之间共享数据上下文

    我的应用程序中有 2 个存储库 每个存储库都有自己的数据上下文对象 最终结果是我尝试将从一个存储库检索到的对象附加到从另一个存储库检索到的对象 这会导致异常 Use 构造函数注入将 DataContext 注入每个存储库 public cl
  • java.io.Serialized 在 C/C++ 中的等价物是什么?

    C C 的等价物是什么java io Serialized https docs oracle com javase 7 docs api java io Serializable html 有对序列化库的引用 用 C 序列化数据结构 ht
  • 使用接口有什么好处?

    使用接口有什么用 我听说它用来代替多重继承 并且还可以用它来完成数据隐藏 还有其他优点吗 哪些地方使用了接口 程序员如何识别需要该接口 有什么区别explicit interface implementation and implicit
  • 将 Word 文档另存为图像

    我正在使用下面的代码将 Word 文档转换为图像文件 但是图片显得太大 内容不适合 有没有办法渲染图片或将图片保存到合适的尺寸 private void btnConvert Click object sender EventArgs e
  • glibc 堆一致性检查

    根据2008年的帖子 我现在找不到 glibc 堆检查 http www gnu org s libc manual html node Heap Consistency Checking html在多线程环境中不起作用 现在还是2010年
  • 从 Linux 内核模块中调用用户空间函数

    我正在编写一个简单的 Linux 字符设备驱动程序 以通过 I O 端口将数据输出到硬件 我有一个执行浮点运算的函数来计算硬件的正确输出 不幸的是 这意味着我需要将此函数保留在用户空间中 因为 Linux 内核不能很好地处理浮点运算 这是设
  • 如何在 32 位或 64 位配置中以编程方式运行任何 CPU .NET 可执行文件?

    我有一个可在 32 位和 64 位处理器上运行的 C 应用程序 我试图枚举给定系统上所有进程的模块 当尝试从 64 位应用程序枚举 32 位进程模块时 这会出现问题 Windows 或 NET 禁止它 我认为如果我可以从应用程序内部重新启动
  • 使用自定义堆的类似 malloc 的函数

    如果我希望使用自定义预分配堆构造类似 malloc 的功能 那么 C 中最好的方法是什么 我的具体问题是 我有一个可映射 类似内存 的设备 已将其放入我的地址空间中 但我需要获得一种更灵活的方式来使用该内存来存储将随着时间的推移分配和释放的
  • C#:帮助理解 UML 类图中的 <>

    我目前正在做一个项目 我们必须从 UML 图编写代码 我了解 UML 类图的剖析 但我无法理解什么 lt
  • 为什么 std::strstream 被弃用?

    我最近发现std strstream已被弃用 取而代之的是std stringstream 我已经有一段时间没有使用它了 但它做了我当时需要做的事情 所以很惊讶听到它的弃用 我的问题是为什么做出这个决定 有什么好处std stringstr
  • CMake 无法确定目标的链接器语言

    首先 我查看了this https stackoverflow com questions 11801186 cmake unable to determine linker language with c发帖并找不到解决我的问题的方法 我
  • C++ 条件编译

    我有以下代码片段 ifdef DO LOG define log p record p else define log p endif void record char data 现在如果我打电话log hello world 在我的代码中

随机推荐

  • 无法删除 matplotlib polycollection 中的原点

    我尝试了 matplotlib 教程中的 PolyCollection 示例 并注意到一件奇怪的事情 我无法从轴原点删除这个点 见图 我该如何处理这个问题 from mpl toolkits mplot3d import Axes3D fr
  • 如何从原生 php 转换为 codeigniter

    我有以下数据库和PHP 我正在尝试制作类别菜单的无序列表 原来的 php 是自己工作的 我正在尝试将其转换为 Codeigniter 中的 MVC 以下是我到目前为止所得到的结果 但无法正常工作 如果有人能指出我做错了什么 我将不胜感激 D
  • SQL:如何从单个列中选择满足多个条件的单个 id(“行”)

    我有一个非常窄的表 user id ancestry user id 列是不言自明的 祖先列包含用户祖先的国家 地区 一个用户可以在表上拥有多行 因为一个用户可以拥有来自多个国家 地区的祖先 我的问题是 如何选择祖先来自多个指定国家 地区的
  • 在汇编中生成随机数

    我是汇编新手 在生成随机数时遇到问题 我的代码很简单 它在中生成 100 个数字0 25范围并将它们存储在数组中 我遇到的问题是 当我在emu8086汇编程序成功运行并生成 100 个随机数 并将其存储在数组中 但是当我在masm611 每
  • 如何在 C# 中使用 SqlTransaction

    我正在使用以下代码同时执行两个命令 我使用 SqlTransaction 来确保所有命令都得到执行或回滚 当我在没有 事务 的情况下运行程序时 它运行正常 但是当我对他们使用 交易 时 他们显示错误 My code SqlTransacti
  • 如何在 tsconfig.json 中指定多个源文件夹?

    我目前有以下项目结构 project tsconfig json webpack config js package json node modules lots of dependencies typings lots of d ts f
  • 从应用程序洞察中删除跟踪

    我已使用 Application Insights 在 Azure 中部署了我的项目 部署后 我做了一些测试 了解为什么一些跟踪写入各自的 Application Insights 中 但是 我只想要一个新的 没有任何痕迹 Applicat
  • 向事件添加委托 - 线程安全

    可以从多个线程同时执行以下代码 this sequencer Completed OnActivityFinished 从多个线程向事件处理程序添加委托是否是线程安全的 从多个线程中删除事件处理程序的委托是否是线程安全的 使该线程安全的最简
  • 无法在 Spring 3 REST Web 服务中反序列化 START_ARRAY 令牌之外的对象实例

    我正在利用Spring提供的这个很酷的东西 Spring RESTWebService spring的版本是3 如果我从浏览器访问 URL 我可以看到 JSON 响应 但从客户端端点 Android 应用程序 我收到此错误消息 Caused
  • 单括号和双括号 Numpy 数组有什么区别?

    import numpy as np a np random randn 1 2 b np zeros 1 2 print Data type of A type a print Data type of A type b Output D
  • 针对 XSD 的 XML 验证:元素必须没有字符或元素信息项

    为什么我的 XML 无法根据以下 XSD 进行验证 我的 XML 文件是这样的
  • 如何在模块中导入 lib 文件夹

    我有一个 GAE 应用程序 其中包含三个模块和一个 lib 文件夹 当我尝试从 lib 文件夹导入第 3 方库时 GAE 弹出导入错误 我可以通过将 lib 符号链接到 Module 1 lib 和 Module 2 lib 并在每个模块中
  • 使用 axios 从 React 前端启用 CORS?

    我在前端使用 React 并且从我不拥有的另一个域调用 API 我的 axios 请求 axios requestURL method GET headers Access Control Allow Origin Content Type
  • 我的工具栏在 API 级别 19 (Kitkat) 上不显示,而在 API 级别 21 上显示

    我的代码没有在 Kitkat 上显示工具栏 这是我针对两个 Android 版本的屏幕截图 奇巧版本 棒棒糖版本 这背后的原因可能是什么 清单文件
  • Java 7u51不接受带有自签名证书的JNLP?

    我在网上看到Java版本7u51 将于2014年1月发布 将不再接受我自签名的Java Webstart应用程序 真的吗 如果这是真的 我是否有机会为我的 JNLP 申请构建一个解决方法 以便我即使在 2014 年 1 月之后也能够启动该申
  • Ansible concat vars 到字符串

    我花了一天的大部分时间试图解决这个问题 但到目前为止都失败了 我正在构建一些剧本来自动化 Splunk 中的功能 并尝试将清单组中的主机列表转换为 E G search head 1 2 3 4 5 6 7 8 我从该剧的调试输出中获得的预
  • 是否可以在 setup.py 中表达特定于平台的依赖项,而无需构建特定于平台的 Egg 版本?

    我们有一个占位符 Egg 它不包含任何代码 其存在的目的只是为了从 PyPi 存储库中提取依赖包列表 大多数这些依赖包与平台无关 但有些仅在 Win32 平台上使用 是否有可能以某种方式使依赖项成为有条件的平台 以便我的给定依赖项insta
  • 幕后:ORM 如何“思考”?

    我对 Rails ActiveRecord PHP Doctrine 以及类似的 ORM 背后的一些设计感兴趣 ORM 如何设法实现链式访问器等功能以及它们通常期望工作的深度 ORM 如何在内部构造查询 ORM 如何管理查询 同时维持所有预
  • javascript 设置标头 Access-Control-Allow-Origin [重复]

    这个问题在这里已经有答案了 我正在用 POST 测试 JS 但我并没有取得成功 使用代码 div testing js div
  • GCC 内联汇编:约束

    我很难理解 GCC 内联汇编 x86 中的角色约束 我有阅读手册 http gcc gnu org onlinedocs gcc Constraints html Constraints 它准确地解释了每个约束的作用 问题是 尽管我了解每个