加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Windows > 正文

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

发布时间:2020-12-13 21:04:39 所属栏目:Windows 来源:网络整理
导读:我很好奇,看看我的64位应用程序是否遇到对齐错误。 从Windows Data Alignment on IPF,x86,and x64: In Windows,an application program that generates an alignment fault will raise an exception, EXCEPTION_DATATYPE_MISALIGNMENT . On the Itanium ,b
我很好奇,看看我的64位应用程序是否遇到对齐错误。

从Windows Data Alignment on IPF,x86,and x64:

In Windows,an application program that generates an alignment fault will raise an exception,EXCEPTION_DATATYPE_MISALIGNMENT.

  • On the Itanium,by default,the operating system (OS) will make this exception visible to the application,and a termination handler might be useful in these cases. If you do not set up a handler,then your program will hang or crash. In Listing 3,we provide an example that shows how to catch the EXCEPTION_DATATYPE_MISALIGNMENT exception.

  • On the x86 architecture,the operating system does not make the alignment fault visible to the application. On these two platforms,you will also suffer performance degradation on the alignment fault,but it will be significantly less severe than on the Itanium,because the hardware will make the multiple accesses of memory to retrieve the unaligned data.

  • On the x64 architecture,the alignment exceptions are disabled by default,and the fix-ups are done by the hardware. The application can enable alignment exceptions by setting a couple of register bits,in which case the exceptions will be raised unless the user has the operating system mask the exceptions with SEM_NOALIGNMENTFAULTEXCEPT. (For details,see the AMD Architecture Programmer’s Manual Volume 2: System Programming.)

忽略AMD架构程序员手册的方向,我将反过来咨询Intel 64 and IA-32 Architectures Software Developer’s Manual

5.10.5 Checking Alignment

When the CPL is 3,alignment of memory references can be checked by setting the
AM flag in the CR0 register and the AC flag in the EFLAGS register. Unaligned memory
references generate alignment exceptions (#AC). The processor does not generate
alignment exceptions when operating at privilege level 0,1,or 2. See Table 6-7 for a
description of the alignment requirements when alignment checking is enabled.

优秀。我不知道这是什么意思,但很好。

那还有:

2.5 CONTROL REGISTERS

Control registers (CR0,CR1,CR2,CR3,and CR4; see Figure 2-6) determine operating
mode of the processor and the characteristics of the currently executing task.
These registers are 32 bits in all 32-bit modes and compatibility mode.

In 64-bit mode,control registers are expanded to 64 bits. The MOV CRn instructions
are used to manipulate the register bits. Operand-size prefixes for these instructions
are ignored.

The control registers are summarized below,and each architecturally defined control
field in these control registers are described individually. In Figure 2-6,the width of
the register in 64-bit mode is indicated in parenthesis (except for CR0).
CR0 — Contains system control flags that control operating mode and states of
the processor

AM
Alignment Mask (bit 18 of CR0) — Enables automatic alignment checking
when set; disables alignment checking when clear. Alignment checking is
performed only when the AM flag is set,the AC flag in the EFLAGS register is
set,CPL is 3,and the processor is operating in either protected or virtual-
8086 mode.

我试过了

我实际使用的语言是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
}

第一条说明

mov rax,cr0;

失败的特权指令例外。

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

PUSHF

我发现x86有指令:

> PUSHF,POPF:首先将/打开16位的EFLAGS推/出栈
> PUSHFD,POPFD:将所有32位的EFLAGS推入/全部打开/关闭堆栈

那就让我进入x64版本:

> PUSHFQ,POPFQ:推/拉堆叠中的RFLAGS quad

(在64位世界中,EFLAGS被重命名为RFLAGS)。

我写道:

void EnableAlignmentExceptions;
{
    asm
       PUSHFQ;                //Push RFLAGS quadword onto the stack
       POP       RAX;         //Pop them flags into RAX
       OR        RAX,$20000; //set bit 18 (AC=Alignment Check) of the flags
       PUSH      RAX;         //Push the modified flags back onto the stack
       POPFQ;                 //Pop the stack back into RFLAGS;
}

它没有崩溃或触发保护异常。我不知道如果它是我想要的。

在x64上运行的应用程序可以访问一个标志寄存器(有时称为 EFLAGS)。该寄存器中的位18允许应用程序在发生对齐错误时获得异常。所以在理论上,所有的程序都必须做,以使对齐错误的异常是修改标志寄存器。

然而

为了实际工作,操作系统内核必须设置cr0的位18来允许它。而Windows操作系统却没有这样做。为什么不?谁知道?

应用程序无法在控制寄存器中设置值。只有内核才能做到这一点。设备驱动程序在内核中运行,所以他们也可以设置这个。

可以通过创建设备驱动程序(参见http://blogs.msdn.com/b/oldnewthing/archive/2004/07/27/198410.aspx#199239和以下注释)来弄脏并尝试使其正常工作。请注意,这篇文章已经十多年了,所以一些链接已经死了。

你也可能会发现这个评论(和这个问题中的其他一些答案)是有用的:

07003

We actually built a version of NT with alignment exceptions turned on for x86 (you can do that as Skywing mentioned).

We quickly turned it off,because of the number of apps that broke

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读