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

GCC内联程序集副作用

慕容灿
2023-03-14
asm ("sumsq %0, %1, %2"
 : "+f" (result)
 : "r" (x), "r" (y), "m" (*x), "m" (*y));

这里是一个虚拟的*z++=*x++**y++指令。请注意,x、y和z指针寄存器必须指定为输入/输出,因为asm会修改它们。

asm ("vecmul %0, %1, %2"
 : "+r" (z), "+r" (x), "+r" (y), "=m" (*z)
 : "m" (*x), "m" (*y));

在第一个示例中,在输入操作数中列出*x*y有什么意义?同一份文件指出:

特别是,如果不将输入操作数指定为输出操作数,就无法指定输入操作数被修改。

void swap_2 (int *a, int *b)
{
int tmp0, tmp1;

__asm__ volatile (
    "movl (%0), %k2\n\t" /* %2 (tmp0) = (*a) */
    "movl (%1), %k3\n\t" /* %3 (tmp1) = (*b) */
    "cmpl %k3, %k2\n\t"
    "jle  %=f\n\t"       /* if (%2 <= %3) (at&t!) */
    "movl %k3, (%0)\n\t"
    "movl %k2, (%1)\n\t"
    "%=:\n\t"

    : "+r" (a), "+r" (b), "=r" (tmp0), "=r" (tmp1) :
    : "memory" /* "cc" */ );
}

共有1个答案

祝花蜂
2023-03-14

在第一个示例中,*x*y必须被列为输入操作数,以便GCC知道指令的结果依赖于它们。否则,GCC可能会通过内联程序集片段将存储区移动到*x*y中,从而访问未初始化的内存。这一点可以通过编译这个示例看出:

double
f (void)
{
  double result;
  double a = 5;
  double b = 7;
  double *x = &a;
  double *y = &b;
  asm ("sumsq %0, %1, %2"
       : "+X" (result)
       : "r" (x), "r" (y) /*, "m" (*x), "m" (*y)*/);
  return result;
}

其结果是:

f:
    leaq    -16(%rsp), %rax
    leaq    -8(%rsp), %rdx
    pxor    %xmm0, %xmm0
#APP
# 8 "t.c" 1
    sumsq %xmm0, %rax, %rdx
# 0 "" 2
#NO_APP
    ret

这两条leaq指令只是设置寄存器指向堆栈上未初始化的红色区域。任务没了。

 类似资料:
  • 我正在尝试为高度优化的x86-64位操作代码编写一个小型库,并且正在摆弄内联ASM。 在gcc和icc中编译和运行都很好,但是当我检查程序集时,我发现了差异 我在想为什么这么复杂?我正在编写高性能代码,其中指令的数量是关键的。我特别想知道为什么gcc在将变量传递给第二个内联ASM之前会对它进行复制? 尽管gcc决定将变量保存在堆栈中,而不是寄存器中,但我不明白的是,为什么要在将传递给第二个ASM之

  • 我在函数中有以下代码: 现在我不知道为什么这不起作用。Gcc说:“错误:'asm'操作数有不可能的约束”我一直在学习Gcc内联汇编教程,我认为这是将参数从c代码带到内联汇编块的正确方法。 我还使用了为32位x86构建的gcc交叉编译器。

  • GCC内联程序集错误:错误:表达式后的垃圾`(%esp)' 我在研究gcc内联汇编。我的环境是Win 7 32bit,mingw-gcc 4.6.1。 我有个关于'm'约束的问题。下面是我的c函数代码:

  • 对于这种特定的情况,目标平台是一个ARM7系统,代码正在用GCC5.3.0进行编译。正在执行的系统调用具有与C函数调用相同的调用约定。经过一些尝试和错误,我得到了上面的“工作”,但我还不相信它是正确的,并且会一直工作,服从于优化编译器的奇思妙想。 我希望能够删除“内存”clobber,并确切地告诉GCC哪些内存将被修改,但是GCC扩展的Asm文档讨论了如何为特定寄存器赋值,然后是内存约束,但如果它

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

  • GCC扩展内联汇编 使用GCC扩展内联汇编的例子如下: #define read_cr0() ({ \ unsigned int __dummy; \ __asm__( \ "movl %%cr0,%0\n\t" \ :"=r" (__dummy)); \ __dummy; \ }) 它代表什么含义呢?这需要从其基本格式讲起。GCC扩展内联汇编的基本格式是: asm [volat