【发布时间】:2019-02-05 22:31:52
【问题描述】:
问题: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 指令上收到了分段错误信号。我检查了有关对齐的文档,我认为这一切都是正确的。对于它的价值,我正在 i5 8600K 上运行和执行它。
我也看过这个similar question。但是我不能真正将他的问题的答案应用于我的问题(与他的内联汇编有关)。如果有人可以对此进行权衡,我将不胜感激!
【问题讨论】:
-
好吧,既然你已经在你的调试器中,那么你看看实际地址来验证它是否对齐如何?您确实意识到使用
ymm0意味着您必须有 32 字节对齐,对吧?所以你应该改成align 32。手册上说得很清楚:“当源或目的操作数是内存操作数时,操作数必须在16字节(128位版本)、32字节(VEX.256编码版本)上对齐” -
@Jester 我正在使用由 Rey Sethfarth 编写的指南。我相信他的话,但他提到需要 16 字节对齐。我看到他没有具体说明什么......(FWIW 它们在 GDB 中是 16 字节对齐的。但不是 32)
-
@Jester 这正是问题所在。对不起,我没有 RTFM。我只是有点坚持我正在阅读的这本书,并坚持我从中获得的信息。如果你把它写成答案,我会接受。
标签: assembly x86-64 nasm memory-alignment avx