当前位置: 首页 > 知识库问答 >
问题:

数组的gcc内联asm输入和输出参数?

彭礼骞
2023-03-14

我的理解是,当编写gcc样式的内联asm时,您必须非常具体和准确地了解所有的输入和输出参数(和clobbers),这样编译器就会确切地知道如何为代码分配寄存器,以及它可以对那些寄存器的值和asm代码可能读取和/或修改的任何内存假设什么。编译器使用这些信息尽可能地优化周围的代码(如果它认为内联asm对任何东西都没有影响,甚至完全删除它)。对此不够具体可能会导致不正确的行为,因为编译器是根据您的不正确的规范做出假设的。

对于我来说,当涉及数组时,我应该如何准确地指定asm正在读写的内容,这一点有点不清楚。如果我不告诉编译器我正在读取和/或写入整个数组,它可能会做出错误的假设,并以这样一种方式优化代码,从而导致不正确的行为。

假设我有两个大小为n无符号int数组,比方说array1array2,我的asm代码读取这两个数组,并将新数据写入array1。这是告诉编译器这件事的正确方法吗?

asm("some asm here using %[array1] and %[array2]"
    : "+m"(*(unsigned(*)[N])array1)
    : [array1]"r"(array1), [array2]"r"(array2),
      "m"(*(unsigned(*)[N])array1),
      "m"(*(unsigned(*)[N])array2)
    : /* possible clobbers, like "cc" */);

这至少使我当前的代码可以工作,但我不是100%确定这是否确实应该这样做。(编译器是否只有在输入和输出参数实际在asm代码字符串中使用时才为这些参数分配寄存器?换句话说,那些额外的输入和输出仅仅是为了告诉编译器我们正在读写它们的全部内容而存在的,不会导致编译器不必要地为它们分配寄存器或其他东西?)

GCC自己的文档提到了输出数组的语法,但似乎没有提到输入数组,所以我在这里只是胡乱猜测。

共有1个答案

薛涛
2023-03-14

是的,在我看来是正确的,只是“+m”使同一数组的“m”输入是多余的。只对读/写数组使用“+m”,对只读数组使用“m”。但使用与您正在做的相同的转换到数组。

独立的输入和“=m”输出操作数在理论上可以告诉编译器它可以将您的asm用作复制操作(所以不要这样做,除非您使用不同的指针读取输入和写入输出)。虽然与标量不同,但我不认为GCC会发明一个数组的新副本。但是“+m”表示就地修改,这样编译器就没有这个选项了。

查看如何指示内联ASM参数“指向”的内存可能被使用?(这个问题几乎是那个问题的重复)。它显示了一个使用任意长度*(const char(*)[])输入的输入数组示例。在实践中,如果[N]不是编译时常量,那么它似乎会被忽略(视为无界),这意味着整个对象都可能被访问。例如,gcc不会使用(int(*)[N])围绕asm语句优化或重新排序存储到arr[N+1],除非N是编译时常量。

还要注意,如果您的输入确实是一个C数组,而不仅仅是一个指针,则不需要任何强制转换。int arr[1024]作为“m”(arr)输入是指整个数组,并且不会衰减为内存中的指针。

(编译器是否只有在输入和输出参数实际用于asm代码字符串时才为这些参数分配寄存器?

不,操作数的寄存器分配与它们是否实际填写在模板中是分开的。

如果没有适当的虚拟输入来覆盖数组(或“memory”clobber),则可以使用asm语句消除死区或重新排序存储。(例如foo[2]=1;asm();foo[2]=3;可以较晚移动第一个存储区,或较早移动第二个存储区,并且只移动一个存储区。

 类似资料:
  • 我正在尝试同时处理MSVC和GCC编译器,同时更新这个代码库以在GCC上工作。但我不确定GCCs内联ASM是如何工作的。现在我并不擅长将ASM转换为C,否则我就会使用C而不是ASM。 我假设ROR13的工作方式类似于,但代码不会产生相同的输出。 什么是将这个内联ASM翻译成GCC的正确方法,或者这个代码的C翻译是什么?

  • 谢谢你的帮助。

  • 在寄存器约束下的扩展GCC ash中正确使用多个输入和输出操作数是什么?考虑我的问题的最小版本。以下是GCC、AT中的简短扩展ash代码 根据https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html语法似乎是正确的,但是,我一定忽略了什么,或者犯了一些我出于某种原因看不到的微不足道的错误。 GCC 5.3.0 p1.0(无编译器参数)的输出是: 输出

  • 我正在学习如何使用Mybatis。老实说,我很喜欢这个框架。它很容易使用,我对它很满意,因为我可以使用它的sql命令:)我使用MyBatis 3.4.2和PostgreSQL数据库。 例如,我喜欢在插入之前使用注释执行查询是多么容易。如果我在接口方法之前添加一些注释,那么数据映射就像一个迷人的例子,比如:。 我不喜欢的(我希望你能把我引向正确的方向)有以下几点: 使用JDBC时,我需要做到以下几点

  • 2.6 数据的输入和输出 任何程序都需要与用户进行沟通,这就要求程序具有输入输出的功能。输入是指程序从 用户那儿获取数据,输出是指程序向用户显示或打印数据。 程序中负责与用户沟通的部分称为用户界面,它是程序设计的一个重要组成部分。设计 用户界面时要遵循的一个主要原则是所谓“用户友好性”,即要让用户在与计算机程序交互 时感到非常简单、方便和不易犯错。本章只讨论简单的数据输入输出,本书后文将专门讨论

  • 我不明白为什么< code>gcc -S -m32会产生这些特定的代码行: C 代码: 它给出以下输出: