相关疑难解决方法(0)

如何在x64上为我的进程启用对齐异常?

我很想知道我的64位应用程序是否存在对齐错误.

IPF,x86和x64上的Windows数据对齐:

在Windows中,生成对齐错误的应用程序将引发异常,EXCEPTION_DATATYPE_MISALIGNMENT.

  • 在x64体系结构上,默认情况下禁用对齐异常,并且修复由硬件完成.应用程序可以通过设置几个寄存器位来启用对齐异常,在这种情况下,除非用户使操作系统屏蔽异常,否则将引发异常SEM_NOALIGNMENTFAULTEXCEPT.(有关详细信息,请参阅AMD体系结构程序员手册第2卷:系统编程.)

[编者按:强调我的]

  • 在x86体系结构中,操作系统不会使对齐故障对应用程序可见.在这两个平台上,您还会在对齐故障方面遇到性能下降,但它的严重程度将远远低于Itanium,因为硬件将对内存进行多次访问以检索未对齐的数据.

  • 在Itanium上,默认情况下,操作系统(OS)将使该异常对应用程序可见,并且在这些情况下终止处理程序可能很有用.如果您没有设置处理程序,那么您的程序将挂起或崩溃.在清单3中,我们提供了一个示例,说明如何捕获EXCEPTION_DATATYPE_MISALIGNMENT异常.

忽略了参考AMD架构程序员手册的方向,我将参考英特尔64和IA-32架构软件开发人员手册

5.10.5检查对齐

当CPL为3时,可以通过设置CR0寄存器中的AM标志和EFLAGS寄存器中的AC标志来检查存储器参考的对齐情况.未对齐的内存引用会生成对齐异常(#AC).在特权级别0,1或2下操作时,处理器不会生成对齐异常.有关在启用对齐检查时对齐要求的说明,请参阅表6-7.

优秀.我不确定这意味着什么,但非常好.

然后还有:

2.5控制寄存器

控制寄存器(CR0,CR1,CR2,CR3和CR4;见图2-6)确定处理器的操作模式和当前正在执行的任务的特性.在所有32位模式和兼容模式下,这些寄存器均为32位.

在64位模式下,控制寄存器扩展到64位.MOV CRn指令用于操作寄存器位.这些指令的操作数大小前缀将被忽略.

控制寄存器总结如下,并且这些控制寄存器中的每个架构定义的控制字段被单独描述.在图2-6中,64位模式下寄存器的宽度用括号表示(CR0除外).- CR0 - 包含控制处理器的操作模式和状态的系统控制标志

在此输入图像描述

AM
对齐掩码(CR0的第18位) - 设置时启用自动对齐检查; 清除时禁用对齐检查.仅当AM标志置位,EFLAGS寄存器中的AC标志置位,CPL为3,处理器工作在受保护或虚拟8086模式时,才执行对齐检查.

我试过了

我实际使用的语言是Delphi,但假装它是与语言无关的伪代码:

void UnmaskAlignmentExceptions()
{
   asm
      mov rax, cr0; //copy CR0 flags into RAX
      or  rax, 0x20000; //set bit 18 (AM)
      mov cr0, rax; //copy flags back
}
Run Code Online (Sandbox Code Playgroud)

第一条指令

mov rax, cr0;
Run Code Online (Sandbox Code Playgroud)

没有特权指令例外.

如何在x64上为我的进程启用对齐异常?

PUSHF

我发现x86有以下指令:

  • PUSHF,POPF …

windows assembly x86-64

23
推荐指数
1
解决办法
1716
查看次数

x86上的错误对齐指针

有人提供一个示例是否会因为错位而将指针从一种类型转换为另一种类型失败?

在对这个答案的评论中,两者都表示做了类似的事情

char * foo = ...;
int bar = *(int *)foo;
Run Code Online (Sandbox Code Playgroud)

如果启用了对齐检查,即使在x86上也可能导致错误.

set $ps |= (1<<18)在GDB中设置对齐检查标志后尝试生成错误条件,但没有任何反应.

工作(即非工作;))示例是什么样的?


答案中没有任何代码片段在我的系统上失败 - 我将尝试使用不同的编译器版本,稍后在不同的PC上.

顺便说一句,我自己的测试代码看起来像这样(现在也使用asm来设置AC标志和未对齐的读写):

#include <assert.h>

int main(void)
{
    #ifndef NOASM
    __asm__(
        "pushf\n"
        "orl $(1<<18),(%esp)\n"
        "popf\n"
    );
    #endif

    volatile unsigned char foo[] = { 1, 2, 3, 4, 5, 6 };
    volatile unsigned int bar = 0;

    bar = *(int *)(foo + 1);
    assert(bar == 0x05040302);

    bar = *(int *)(foo + 2);
    assert(bar == 0x06050403);

    *(int …
Run Code Online (Sandbox Code Playgroud)

c pointers casting alignment

19
推荐指数
3
解决办法
1万
查看次数

如何获得"总线错误"?

我正在努力解决总线错误.

一种方法是错位访问,我尝试了这里这里给出的例子,但没有错误对我来说 - 程序执行得很好.

是否存在一些肯定会产生总线错误的情况?

c++ bus-error

15
推荐指数
3
解决办法
1万
查看次数

标签 统计

alignment ×1

assembly ×1

bus-error ×1

c ×1

c++ ×1

casting ×1

pointers ×1

windows ×1

x86-64 ×1