【发布时间】:2021-07-24 16:26:37
【问题描述】:
我正在尝试使用汇编指令从内存中收集 64 位整数。下面你可以看到我是如何从C 调用assembly 代码的。请注意,汇编代码使用NASM 语法。
nasm_gather.asm文件
bits 64
section .text
global nasm_gather:function
extern base_addr
extern vindex
nasm_gather:
; prolog
push rbp
push rbx
push r12
push r13
mov r12 ,[rel base_addr] ; r12 point to base_addr
mov r13 ,[rel vindex] ; r13 points to vindex
vmovdqu32 zmm1 ,[r13] ; zmm1 = [2, 5, 1, 3, 0, 4, 7, 6]
vpxorq zmm2 ,zmm2 ,zmm2 ; zmm2 = [0, 0, 0, 0, 0, 0, 0, 0]
vpgatherqq zmm2 ,[r12 + zmm1*8] ; ----> Illegal instruction at address = ...
...
; epilog
pop r13
pop r12
pop rbx
pop rbp
ret
main.cpp文件
#include <iostream>
#include <immintrin.h>
using namespace std;
extern "C" int nasm_gather();
const int N=32;
int64_t* base_addr /*__attribute__ ((aligned (64)))*/ = (int64_t *) malloc(sizeof(int64_t) * N);
int64_t* vindex = (int64_t *) malloc(sizeof(int64_t) * 8);
int main() {
/* initialize indices */
vindex[0]=2; vindex[1]=5; vindex[2]=1; vindex[3]=3;
vindex[4]=0; vindex[5]=4; vindex[6]=7; vindex[7]=6;
// ...
int64_t result = nasm_gather();
...
return 0;
}
(vpgatherqq zmm, vm64z汇编指令对应C中的_mm512_i64gather_epi64内部函数)
正如程序到达这一点:
vpgatherqq zmm2 ,[r12 + zmm1*8]
我收到非法指令错误:
地址非法指令 = 4011f0: 62 d2 fd 48 91 14 cc 62 f1 7e 48 6f c2 e8 10
如果您认为您的应用程序应该尝试 执行这条非法指令(以及其他可能存在的指令), 然后使用这个旋钮:-emit-illegal-insts 0,这个错误信息将 避免。
有什么问题?
【问题讨论】:
-
mov r12, [rel base_addr]将使用来自base_addr[0]的值加载r12,而我认为您只希望它包含base_addr的地址。所以我认为你想要lea r12, [rel base_addr]。对于以下行也是如此。虽然我仍然希望出现分段错误而不是非法指令。 -
@NateEldredge 我收到相同的错误消息
Illegal instruction at address = 4011dc: 62 d2 fd 48 91 14 cc 62 f1 7e 48 6f c2 e8 07 -
但是说真的,如果你只想使用 C 中的
vpgatherqq,请使用immintrin.h中的_mm512_mask_i64gather_epi64。 software.intel.com/sites/landingpage/IntrinsicsGuide/…。并且不要使用全局变量来传递参数!我希望您实际上并不打算将其用于性能。 -
您是否告诉您的模拟器启用 AVX-512?是哪个模拟器?另请注意,您的评论是错误的; kxnorW 将产生 65535。或者正如大多数人所写的那样,-1 或 0xFFFF
-
@him 您没有回答彼得关于您使用的是什么模拟器(或您传递给它的参数)的问题。在您的情况下,这将是 minimal reproducible example 的一部分(以及实际编译的代码,即摆脱
...)
标签: c++ assembly nasm simd avx512