- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我读到,如果可以修改 eflags 位 18(AC - 对齐检查),您就知道 CPU 是 486 或更新版本。在 386 上,该位无法修改。
我从 this site 中提取了以下汇编代码并添加了详尽的注释(保留奇怪的语法完整):
asm
mov bx,sx ; Save the stack pointer to bx (is sx a typo or a real register?).
and sp,$fffc ; Truncate the stack pointer to a 4-byte boundary.
pushfl ; Push the eflags register to the stack.
pop eax ; Pop it into eax.
mov ecx,eax ; Save the original eflags value into ecx.
xor eax,$40000 ; Flip bit 18 in eax.
push eax ; Push eax to the stack.
popfl ; Pop modified value into eflags.
pushfl ; Push eflags back onto the stack.
pop eax ; Pop it into eax.
xor eax,ecx ; Get changed bits from the original value.
setz al ; Set al register to 1 if no bits changed (0 otherwise).
and sp,$fffc ; Truncate the stack pointer to a 4-byte boundary.
push ecx ; Push ecx (original eflags) to stack.
popfl ; Pop it into eflags to restore the original value.
mov sp,bx ; Restore the original stack pointer.
end ['eax','ebx','ecx'];
如果 al 寄存器最后设置为 1(假设从一开始它并不旧),则 CPU 是 386,否则是 486 或更新版本。我理解这部分。
我不明白的是,为什么在进行标志修改测试之前必须将堆栈指针截断到4字节边界?我假设它是为了设置位 18,因为它毕竟是对齐位...但是与 0x40000 的异或将翻转该位,无论其值如何。换句话说,无论初始值如何,修改测试都应该得到相同的结果,对吧?
如果答案是否定的,我对“为什么”的最佳[未受过教育的]猜测是,“也许下面的入栈/出栈指令可以强制对齐?这将对齐之前未对齐的堆栈指针并导致对齐位从0到1本身。这样的话,修改成功就会显得不成功,反之亦然。” (编辑:这绝对是不正确的,因为对齐位是关于强制而不是跟踪对齐。另外,我怀疑 pop/push 无论如何都会在以前未对齐的堆栈上强制对齐。)
即使是这种情况,测试后再次对齐堆栈指针(在恢复原始 eflags 和堆栈指针之前)的目的是什么?之前不应该已经在 4 字节边界上了吗?如果不是,那么推送/弹出 4 字节值会如何改变?
总之,有些说明对我来说似乎是多余的,我觉得我一定错过了一些重要的东西。有谁能解释一下吗?
(附带问题:第一行将“sx”中的值复制到 bx 中。我从未在任何地方看到过对 sx 寄存器的引用。它确实存在,还是拼写错误?“x”键离“p”键很远,至少在美国键盘上是这样。)
编辑:现在这个问题已经得到解答,我决定从代码中的两个对齐行中删除不正确的注释。我最初假设对齐堆栈会设置对齐位,并将其写入我的评论中(问题的其余部分继续使用这个不正确的逻辑)。相反,对齐检查位实际上是关于强制对齐(而不是跟踪它),正如 flolo 关于 sigbus 的回答所表明的那样。我决定修复评论以避免让有类似问题的人感到困惑。
最佳答案
我的猜测很简单:代码不想使用 sigbus。如果未设置检查对齐,而您设置了它,则实际上启用了对齐检查(当设置它有效时)。当堆栈指针未与 4 字节边界对齐时,猜猜会发生什么?您进行了未对齐的内存访问,这会导致 sigbus。如果您不想让无效的内存访问发生(因为您只想更改位以进行测试),则必须注意测试时的所有访问都假设最坏的情况(即:您已启用它,并且您的堆栈在未对齐之前,因为它不需要,因为到目前为止检查已被禁用)。
关于assembly - x86 eflags 位 18(对齐检查)如何工作? (与检查 386 与 486 及更高版本相关。),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7531308/
我们都知道,在查看源代码时,可以安全地假设方向标志是明确的。方向标志的概率很低。 我想了解其他标志的概率。这就是为什么我编写了一个测试程序来单步执行我现有的一些软件,为前 12 个 EFLAGS 位中
我正在尝试学习如何编写和理解 x86 Assembly 以及如何有效地使用 GDB 和相关工具。为此,我使用 DDD 作为 GDB 的前端。 我无法理解给出的条件标志(eflags?)是什么,它们似乎
我正在尝试学习如何编写和理解 x86 Assembly 以及如何有效地使用 GDB 和相关工具。为此,我使用 DDD 作为 GDB 的前端。 我无法理解给出的条件标志(eflags?)是什么,它们似乎
我想知道为什么EFLAGS寄存器未定义的第二位默认设置为1。所有其他未定义/保留位都设置为 0。这是否有特殊含义? 最佳答案 它是“保留”,而不是“未定义”。据推测,它反射(reflect)了一些根本
对于我学校的任务,我需要编写一个 C 程序,该程序使用汇编程序执行 16 位加法。除了结果外,还应返回 EFLAGS。 这是我的 C 程序: int add(int a, int b, unsigne
这个问题已经有答案了: Problem switching to v8086 mode from 32-bit protected mode by setting EFLAGS.VM to 1 (2
我正在使用 Win32 API 来停止/启动/检查/更改线程状态。一般来说效果很好。有时它会失败,我试图找出原因。 我有一个线程通过以下方式强制在其他线程上进行上下文切换: thread stop f
这是对 What is "=qm" in extended assembler 的跟进. 使用时 RDRAND ,它设置(或取消设置)进位标志( CF ): char rc; unsigned int
我处于以当前权限级别 (CPL=0) 运行的 32 位保护模式。我试图通过将 EFLAGS.VM(位 17)标志设置为 1(并将 IOPL 设置为 0)并对我的 16 位实模式代码执行 FAR JMP
我读到,如果可以修改 eflags 位 18(AC - 对齐检查),您就知道 CPU 是 486 或更新版本。在 386 上,该位无法修改。 我从 this site 中提取了以下汇编代码并添加了详尽
我是一名优秀的程序员,十分优秀!