当前位置: 首页 > 知识库问答 >
问题:

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

公良理
2023-03-14

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

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

    section .text
        global _start
_start:
        mov [arr], word "abcd"

        section .data
arr: db 1, 2, 3, 4, 5, 6, 7

共有1个答案

龚俭
2023-03-14

通常没有问题,x86允许任何大小的未对齐访问(对于16字节未对齐的访问有一些限制)。

其他一些ISA没有这样做(例如SPARC、MIPS32r6之前的MIPS等),C通过不定义指针小于对齐(t)时的行为来迎合这些ISA。在GNU C中,您可以使用\uu attribute\uu((aligned(1)))来定义在任何对齐中都有明确行为的typedef类型。

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

此外,abcd是一个4字节的常量,必须将其截断才能放入单词中。我猜你在测试你的示例时没有注意到这一点,因为它碰巧在你自己的计算机上工作,然后才问它是否总体安全?

某些处理器UB的原因

不,在ISO C中总是UB。看看为什么对mmap'ed内存的未对齐访问有时会在AMD64上出现故障?例如和链接。请注意,未定义的行为并不意味着它会崩溃,只是优化器可以假设它不会发生,并且结果可能不可预测。

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

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

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

对于AVX/AVX-512编码(VEX/EVEX),未对齐是默认设置(例如vaddps xmm0、xmm1、[rdi]不需要对齐),只有特殊的对齐要求指令,例如vmovntps-store或vmovdqaload/store会在未对齐时出错。

即使对于未对齐的地址,对齐所需访问的行为也有很好的定义:#SSE/AVX未对齐的GP错误,或者#AC,如果您设置了AC位并执行了需要2、4或8字节对齐但未满足该要求的操作。(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(总线错误)。

(传统SSE内存操作数的情况除外。)

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

 类似资料:
  • 问题内容: 我正在开发一个宠物的开源项目,该项目实现了一些流密码算法,并且只有在ARM处理器上运行该bug时,我才遇到问题。我什至尝试在qemu下的x86中运行ARM二进制文件,但该错误并未在那里触发。 该错误的具体机制仍然难以捉摸,但是我最好的选择是相信它是由程序中未对齐的内存访问尝试引起的,这是qemu实现的,但被开发板中的真正ARM处理器默默忽略了。 因此,由于该问题很难诊断,所以我想知道是

  • 也许我误解了什么,但x86中的未对齐访问似乎带来了安全问题,例如返回地址完整性问题。 > 为什么x86设计器首先允许未对齐的访问?(性能是我能想到的唯一好处。) 如果x86设计人员允许这种未对齐的访问问题,他们应该知道如何解决它,不是吗?是否可以使用静态技术或清理技术检测未对齐的访问?

  • 问题内容: 我想用x86 / x86_64上禁止的未对齐内存访问来模拟系统。有一些调试工具或特殊模式可以做到这一点吗? 当使用为SPARC或其他类似CPU设计的软件(C / C ++)时,我想在几台x86 / x86_64 PC上运行许多(CPU密集型)测试。但是我对Sparc的访问受到限制。 据我所知,Sparc总是检查内存读写的对齐是否自然(从任何地址读取一个字节,但仅当地址被4整除时才读取4

  • 我想模拟x86/x86_64上禁止未对齐内存访问的系统。是否有一些调试工具或特殊模式来执行此操作? 当使用为SPARC或其他类似CPU设计的软件(C/C)时,我想在几台x86/x86_64PC上运行许多(CPU密集型)测试。但是我对Sparc的访问是有限的。 正如我所知,Sparc总是检查内存读写的对齐是否正常(从任何地址读取一个字节,但仅当地址可被4整除时才允许读取一个4字节的字)。 可能是Va

  • 我总是听说未对齐的访问是不好的,因为它们要么会导致运行时错误并使程序崩溃,要么会减慢内存访问速度。但是我找不到任何关于它们会减慢多少速度的实际数据。 假设我在x86上并且有一些(但未知的)未对齐访问份额——实际上可能的最糟糕的减速是什么,以及如何在不消除所有未对齐访问并比较两个版本代码的运行时间的情况下估计它?

  • 我正在尝试使用JavaSwing创建一个登录表单。但我希望布局看起来更紧凑,但仍能响应。 我的项目结构 面板中的组件没有像我预期的那样工作,我希望字段靠近标签,但不要水平填充整个空间。 我的代码是: 登录面板 主要的 这就是我希望它看起来的样子(更新):