NASM中是否存在未对齐的访问问题



我知道C中的未对齐访问是什么,它可能会导致一些处理器UB。

我想知道在NASM汇编上写的代码中是否也有同样的问题:

    section .text
        global _start
_start:
        mov [arr], word "abcd"
        section .data
arr: db 1, 2, 3, 4, 5, 6, 7

一般来说,x86允许任何大小的未对齐访问(对16字节的未对齐有一些限制(。

一些其他ISAs没有(例如SPARC、MIPS32r6之前的MIPS等(,并且C通过在T*指针具有小于alignof(T)对齐时不定义行为来迎合这些ISAs。在GNUC中,您可以使用__attribute__((aligned(1)))来对在任何对齐方式下都具有定义良好行为的类型进行typedef。


在Linux下,默认情况下,.data部分将至少对齐4个字节,因此[arr]的2字节(word(存储是对齐存储;地址保证是偶数(除非您使用特殊的链接器选项/链接器脚本来告诉它在奇数地址上启动.data(。arr.data部分的开头开始。

此外,"abcd"是一个4字节的常数,它必须被截断才能适应word。我想当你测试你的例子,看看它恰好在你自己的电脑上运行时,你错过了这一点,然后问它总体上是否安全?

导致某些处理器UB

不,在ISO C中总是UB。请参阅为什么对mmap';ed内存有时会在AMD64上发生故障?例如和链接。请注意,Undefined Behavior并不意味着它崩溃,只是优化器可以假设它不会发生,结果可能是不可预测的。

与大多数ISAs一样,x86中的行为总是定义良好的。即使在引发异常的情况下,硬件供应商也必须准确地指定会发生什么,因此当用户空间导致故障时,可以编写操作系统来保持对机器的控制。(因此,在asm中,你真正想要的不是定义的行为,而是保证不会出错。(

对于除16字节以外的任何访问大小,任何未对准都是可以的。(假设AC位被清除,这是正常系统中的情况。例如,如果您为小型未对齐副本设置它,glibc memcpy就会出错。除非您自己专门设置AC来检测无意的未对齐访问,否则您可以假设它被清除。现代CPU上也有用于拆分加载和拆分存储的性能计数器,您可以使用它来检测问题。(matic的。(

对于16字节访问,传统SSE访问默认情况下需要自然对齐(例如SSE2 pxor xmm0, [rdi]需要对齐(,但movdqu未对齐加载/存储等指令除外。其他大小(如8字节(不需要对齐,例如punpckldq mm0, [rdi]是对齐安全的,因为MMX寄存器只有8字节宽,即使punpck指令令人恼火地进行全宽加载,而不是仅将它们拖到目标的一半。(

对于AVX/AVX-512编码(VEX/EVEX(,未对齐是默认的(例如vaddps xmm0, xmm1, [rdi]不需要对齐(,只有特殊的需要对齐的指令,如vmovntps-存储或vmovdqa加载/存储,才会在未对齐时出错。

即使对于未对齐的地址,对齐所需访问的行为也是明确定义的:SSE/AVX未对齐的#GP错误,或者如果您设置了AC位并执行了需要2、4或8字节对齐但不满足该要求的操作,则为#AC。(https://xem.github.io/minix86/manual/intel-x86-and-64-manual-vol3/o_fe12b1e2a880e0ce-231.html摘录英特尔SDM PDF的相关页面。(

在GNU/Linux下,如果用户空间进程生成#GF异常,它将收到SIGSEGV(分段错误(。IIRC,#AC可能会让内核传递SIGBUS(总线错误(。


x86中未对齐访问的唯一问题是性能

(传统SSE内存操作数除外。(

  • 什么';成功的未对齐访问对x86的实际影响是什么
  • 如何在x86_64上准确地对未对齐的访问速度进行基准测试?我的答案涵盖了在设计基准测试时您想要衡量的一些影响
  • http://blog.stuffedcow.net/2014/01/x86-memory-disambiguation/-存储转发取决于某些CPU上的对齐,尤其是较旧的CPU

相关内容

  • 没有找到相关文章

最新更新