相关疑难解决方法(0)

在C++内联asm中使用基指针寄存器

我希望能够%rbp在内联asm中使用基指针寄存器().这样的玩具示例是这样的:

void Foo(int &x)
{
    asm volatile ("pushq %%rbp;"         // 'prologue'
                  "movq %%rsp, %%rbp;"   // 'prologue'
                  "subq $12, %%rsp;"     // make room

                  "movl $5, -12(%%rbp);" // some asm instruction

                  "movq %%rbp, %%rsp;"  // 'epilogue'
                  "popq %%rbp;"         // 'epilogue'
                  : : : );
    x = 5;
}

int main() 
{
    int x;
    Foo(x);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我希望,因为我使用通常的序幕/结尾函数调用方法来推送和弹出旧的%rbp,这样就可以了.但是,当我尝试在内x联asm之后访问时,它会出现故障.

GCC生成的汇编代码(略微剥离)是:

_Foo:
    pushq   %rbp
    movq    %rsp, %rbp
    movq    %rdi, -8(%rbp)

    # INLINEASM
    pushq %rbp;          // prologue
    movq %rsp, …
Run Code Online (Sandbox Code Playgroud)

c++ x86 assembly red-zone

13
推荐指数
1
解决办法
4119
查看次数

GCC内联汇编程序,混合寄存器大小(x86)

有谁知道如何摆脱以下汇编警告?

代码是x86,32位:

int test (int x)
{
  int y;
  // do a bit-rotate by 8 on the lower word. leave upper word intact.
  asm ("rorw $8, %0\n\t": "=q"(y) :"0"(x));
  return y;
}
Run Code Online (Sandbox Code Playgroud)

如果我编译它,我得到以下(非常有效)警告:

Warning: using `%ax' instead of `%eax' due to `w' suffix
Run Code Online (Sandbox Code Playgroud)

我正在寻找的是告诉编译器/汇编器我想要访问%0的低16位子寄存器的方法.访问字节子寄存器(在本例中为AL和AH)也很好.

我已经选择了"q"修饰符,因此编译器被迫使用EAX,EBX,ECX或EDX.我已经确保编译器必须选择一个具有子寄存器的寄存器.

我知道我可以强制asm-code使用特定的寄存器(及其子寄存器),但我想将寄存器分配作业留给编译器.

x86 assembly gcc gnu-assembler

12
推荐指数
2
解决办法
5792
查看次数

适用于AVX512掩码寄存器(k1 ... k7)的GNU C内联asm输入约束?

AVX512为其算术命令引入了opmask功能。一个简单的示例:godbolt.org

#include <immintrin.h>
__m512i add(__m512i a, __m512i b) {
    __m512i sum;
    asm(
        "mov ebx, 0xAAAAAAAA;                                   \n\t"
        "kmovw k1, ebx;                                         \n\t"
        "vpaddd %[SUM] %{k1%}%{z%}, %[A], %[B];  # conditional add   "
        :   [SUM]   "=v"(sum)
        :   [A]     "v" (a),
            [B]     "v" (b)
        : "ebx", "k1"  // clobbers
       );
    return sum;
}
Run Code Online (Sandbox Code Playgroud)
-march=skylake-avx512 -masm=intel -O3
Run Code Online (Sandbox Code Playgroud)
 mov ebx,0xaaaaaaaa
 kmovw k1,ebx
 vpaddd zmm0{k1}{z},zmm0,zmm1
Run Code Online (Sandbox Code Playgroud)

问题是必须指定k1。

是否有类似于"r"整数的输入约束,除了它选择k寄存器而不是通用寄存器外?

c assembly gcc inline-assembly avx512

6
推荐指数
2
解决办法
222
查看次数

用于读/写 XMM 和 YMM 寄存器的内联汇编代码?

我有 2 个变量来模拟 X86 XMM 和 YMM,如下所示:

uint64_t xmm_value[2];
uint64_t ymm_value[4];
Run Code Online (Sandbox Code Playgroud)

现在我想使用内联汇编来读取和写入 XMM/YMM 寄存器。

  • 如何编写GCC内联汇编来复制xmm_value到寄存器XMM0
  • 如何编写 GCC 内联汇编将寄存器复制YMM0ymm_value

我已经尝试搜索示例内联汇编来执行此操作,但找不到任何好的答案。谢谢!


因此,在一些帮助下,我编写了这段代码,并且编译正常。我用于movupsXMM 和vmovupsYMM,如下所示。这是正确的吗?我还可以优化我的代码吗?

__m128 xmm0;
__m256 ymm0;

// write to XMM0, and read from YMM0
__asm__("movups %1, %%xmm0\n\t"
        "vmovups %%ymm0, %0"
        : "=m"(ymm0)
        : "m"(xmm0)
        : "xmm0", "ymm0");
Run Code Online (Sandbox Code Playgroud)

更新 2:这是我的完整代码(添加了 vpbroadcastb)

__m128 xmm0;
__m256 ymm0;

// write to XMM0, and read from YMM0
__asm__("movups %1, %%xmm0\n\t"
        "vpbroadcastb %%xmm0, %%ymm0\n\t"
        "vmovups …
Run Code Online (Sandbox Code Playgroud)

assembly gcc sse inline-assembly

6
推荐指数
1
解决办法
2678
查看次数

具有内在和汇编的嵌入式广播

英特尔架构指令集扩展编程参考的2.5.3节"广播"中我们学习的比AVX512(和骑士角落)有

用于编码一些加载操作指令的数据广播的位字段,即从存储器加载数据并执行一些计算或数据移动操作的指令.

例如,使用英特尔汇编语法,我们可以在存储的地址广播标量,rax然后乘以16浮点数zmm2并将结果写入zmm1这样的

vmulps zmm1, zmm2, [rax] {1to16}
Run Code Online (Sandbox Code Playgroud)

但是,没有内在的东西可以做到这一点.因此,使用内在函数,编译器应该能够折叠

__m512 bb = _mm512_set1_ps(b);
__m512 ab = _mm512_mul_ps(a,bb);
Run Code Online (Sandbox Code Playgroud)

一个指令

vmulps zmm1, zmm2, [rax] {1to16}
Run Code Online (Sandbox Code Playgroud)

但我没有观察到GCC这样做.我发现了一个GCC错误报告.

我观察到与GCC类似的FMA.例如,GCC 4.9不会崩溃_mm256_add_ps(_mm256_mul_ps(areg0,breg0) 为单个fma指令-Ofast.但是,GCC 5.1确实将它崩溃为一个单一的fma.至少有内在函数可以用FMA做到这一点,例如_mm256_fmadd_ps.但是没有例如_mm512_mulbroad_ps(vector,scalar)内在的.

海湾合作委员会可能会在某个时候解决这个问题,但在此之前,装配是唯

所以我的问题是如何在GCC中进行内联汇编?

我想我可能已经为上面的例子提出了GCC内联汇编的正确语法(但我不确定).

"vmulps        (%%rax)%{1to16}, %%zmm1, %%zmm2\n\t"
Run Code Online (Sandbox Code Playgroud)

我真的在寻找这样的功能

static inline __m512 mul_broad(__m512 a, float b) {
    return a*b;
}
Run Code Online (Sandbox Code Playgroud)

如果b在内存中指向rax它产生

vmulps        (%rax){1to16}, %zmm0, %zmm0
ret
Run Code Online (Sandbox Code Playgroud)

如果b它在xmm1它产生

vbroadcastss …
Run Code Online (Sandbox Code Playgroud)

c assembly gcc intrinsics avx512

5
推荐指数
1
解决办法
653
查看次数

如何在GCC内联汇编中使用标签?

我正在尝试学习x86-64内联汇编,并决定实现这个非常简单的交换方法,只需按顺序排序a并按b升序排序:

#include <stdio.h>

void swap(int* a, int* b)
{
    asm(".intel_syntax noprefix");
    asm("mov    eax, DWORD PTR [rdi]");
    asm("mov    ebx, DWORD PTR [rsi]");
    asm("cmp    eax, ebx");
    asm("jle    .L1");
    asm("mov    DWORD PTR [rdi], ebx");
    asm("mov    DWORD PTR [rsi], eax");
    asm(".L1:");
    asm(".att_syntax noprefix");
}

int main()
{
    int input[3];

    scanf("%d%d%d", &input[0], &input[1], &input[2]);

    swap(&input[0], &input[1]);
    swap(&input[1], &input[2]);
    swap(&input[0], &input[1]);

    printf("%d %d %d\n", input[0], input[1], input[2]);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

当我使用此命令运行它时,上面的代码按预期工作:

> gcc main.c
> ./a.out
> 3 2 1
> 1 …
Run Code Online (Sandbox Code Playgroud)

c assembly gcc inline-assembly

2
推荐指数
1
解决办法
3902
查看次数

在内联汇编中使用特定的 zmm 寄存器

我可以告诉gcc 风格的内联汇编将我的__m512i变量放入特定的 zmm寄存器中,例如zmm31

x86 assembly gcc inline-assembly

2
推荐指数
1
解决办法
1389
查看次数

标签 统计

assembly ×7

gcc ×6

inline-assembly ×4

c ×3

x86 ×3

avx512 ×2

c++ ×1

gnu-assembler ×1

intrinsics ×1

red-zone ×1

sse ×1