Yasm:vmovaps指令导致分段错误 [英] YASM: vmovaps instruction causing segmentation fault
问题描述
问题:movaps
出现分段错误。
上下文:x86-64指令vmovaps
旨在与Core I系列处理器(我正在运行此系统)上的AVX寄存器一起使用。AVX寄存器的宽度是SSE寄存器的两倍(分别为256位和128位)。指令vmovaps
应将对齐的浮点值(32位)向量移入指定的ymm
寄存器。
可能的原因:源数据的对齐特别重要,因为不正确对齐的数据是分段错误的来源。然而,即使我已经对齐了我的数据,我自己也遇到了分段错误。
示例
segment .data
align 16
xs:
dd 0.0
dd 1.1
dd 2.2
dd 3.3
dd 4.4
dd 5.5
dd 6.6
dd 7.7
align 16
ys:
dd 8.8
dd 7.7
dd 6.6
dd 5.5
dd 4.4
dd 3.3
dd 2.2
dd 1.1
segment .text
global main
main:
push rbp
mov rbp, rsp
; Move eight 32-bit floats from "xs" into ymm0
vmovaps ymm0, [xs]
; Move eight 32-bit floats from "ys" into ymm1
vmovaps ymm1, [ys]
; Add all eight to each other simulatenously, put in ymm0
vaddps ymm0, ymm1
xor rax, rax
leave
ret
使用:yasm -f elf64 -g dwarf2 <filename>
链接:gcc -o <bin-name> <filename>.o
当我使用gdb运行此命令时,它只报告在第一个vmovaps
指令上收到分段错误信号。我已经检查了有关调整的文档,我认为它们都是正确的。不管它有什么价值,我是在i58600K上运行和执行这个程序的。
我也看过这个similar question。然而,我真的不能将他的问题的答案应用到我的问题上(与他的内联汇编有关)。如果有人能参与进来,我将不胜感激!
推荐答案
vmovaps
和ymm0
操作数需要32字节对齐。引用the manual:
当源或目标操作数是内存操作数时, 操作数必须在16字节(128位版本)、32字节上对齐 (VEX.256编码版本)或64字节(EVEX.512编码版本) 边界或一般保护例外(#GP)将被生成。 对于EVEX.512编码版本,操作数必须与大小对齐 内存操作数的。
(已添加强调)。Linux将SIGSEGV传递给导致#GP异常的进程。
因此,您应该将dd
元素的静态数组的align 16
更改为align 32
或使用vmovups
未对齐的加载,并让硬件处理它;对碰巧对齐的数据具有相同的速度,对于不跨缓存行边界拆分的加载/存储也是在大多数CPU上。
相关:How to solve the 32-byte-alignment issue for AVX load/store operations?用于C和C++对齐对象的方式,包括自动(堆栈)或动态存储中的数组。
这篇关于Yasm:vmovaps指令导致分段错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!