我希望能够%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) 有谁知道如何摆脱以下汇编警告?
代码是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使用特定的寄存器(及其子寄存器),但我想将寄存器分配作业留给编译器.
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寄存器而不是通用寄存器外?
我有 2 个变量来模拟 X86 XMM 和 YMM,如下所示:
uint64_t xmm_value[2];
uint64_t ymm_value[4];
Run Code Online (Sandbox Code Playgroud)
现在我想使用内联汇编来读取和写入 XMM/YMM 寄存器。
xmm_value到寄存器XMM0?YMM0到ymm_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) 在英特尔架构指令集扩展编程参考的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) 我正在尝试学习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) 我可以告诉gcc 风格的内联汇编将我的__m512i变量放入特定的 zmm寄存器中,例如zmm31?