YASM:导致分段错误的 vmovaps 指令
YASM: vmovaps instruction causing segmentation fault
问题:movaps
给我一个分段错误。
上下文:x86-64指令vmovaps
设计用于Core i系列处理器(我是运行宁这个系统)。 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
指令上收到了分段错误信号。我已经检查了有关对齐的文档,我认为这一切都是正确的。对于它的价值,我正在 运行 宁并在 i5 8600K 上执行它。
我也看过这个。但是我不能真正将他的问题的答案应用到我的问题上(与他的内联汇编有关)。如果有人能对此发表意见,我将不胜感激!
vmovaps
和 ymm0
操作数需要 32 字节对齐。引用 the manual:
When the source or destination operand is a memory operand, the
operand must be aligned on a 16-byte (128-bit version), 32-byte
(VEX.256 encoded version) or 64-byte (EVEX.512 encoded version)
boundary or a general-protection exception (#GP) will be generated.
For EVEX.512 encoded versions, the operand must be aligned to the size
of the memory operand.
(强调)。 Linux 将 SIGSEGV 传递给导致 #GP 异常的进程。
因此,对于 dd
个元素的静态数组,您应该将 align 16
更改为 align 32
或者使用vmovups
非对齐加载,让硬件来处理;恰好对齐的数据速度相同,并且在大多数 CPU 上也适用于 loads/stores 不跨越缓存行边界的数据。
相关: C 和 C++ 对齐方式,包括自动(堆栈)或动态存储中的数组。
问题:movaps
给我一个分段错误。
上下文:x86-64指令vmovaps
设计用于Core i系列处理器(我是运行宁这个系统)。 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
指令上收到了分段错误信号。我已经检查了有关对齐的文档,我认为这一切都是正确的。对于它的价值,我正在 运行 宁并在 i5 8600K 上执行它。
我也看过这个
vmovaps
和 ymm0
操作数需要 32 字节对齐。引用 the manual:
When the source or destination operand is a memory operand, the operand must be aligned on a 16-byte (128-bit version), 32-byte (VEX.256 encoded version) or 64-byte (EVEX.512 encoded version) boundary or a general-protection exception (#GP) will be generated. For EVEX.512 encoded versions, the operand must be aligned to the size of the memory operand.
(强调)。 Linux 将 SIGSEGV 传递给导致 #GP 异常的进程。
因此,对于 dd
个元素的静态数组,您应该将 align 16
更改为 align 32
或者使用vmovups
非对齐加载,让硬件来处理;恰好对齐的数据速度相同,并且在大多数 CPU 上也适用于 loads/stores 不跨越缓存行边界的数据。
相关: