【问题标题】:x86 - Get the current state of the direction flag (DF)x86 - 获取方向标志 (DF) 的当前状态
【发布时间】:2017-07-25 11:06:28
【问题描述】:

我正在尝试从 EFLAGS 寄存器中获取 DF 的值。 我尝试使用 LAHF 指令,但根据 Intel X86 文档,该指令仅加载 SF, ZF, AF, PF, CF 标志。但是,我正在尝试找到一条指令,它可以为我提供 DF 寄存器的值。

提前致谢。

【问题讨论】:

  • pushf 然后检查堆栈。

标签: c windows debugging assembly x86


【解决方案1】:

使用以下代码:

pushf                ;Maybe you'll need pushfd
pop  eax
bt   eax, 10

如果设置了 CF,则设置了 DF!


如果你不想破坏任何寄存器,你可以使用下一个方法(受@fuz 启发):

pushf
test byte [esp+1],4
lea  esp, [esp+4]      ;The LEA instruction doesn't change any flags

这次如果设置了ZF,就说明DF被清除了!

【讨论】:

  • 稍微好一点的可能是pushf; test byte [esp+1],4
  • @fuz 它还需要弹出(当然不改变标志)!你的目标是不破坏注册表吗?
  • @SepRoland 是的。所以总的操作就是pushf ; test byte [esp+1],4 ; add esp, 4。或者下次需要调整堆栈时弹出。
  • @fuz 那么也许是一个对代码放置更宽容的解决方案:pushftest byte [esp+1],4 ; lea esp, [esp+4] 测试结果仍然可用。
【解决方案2】:

这也可以使用内部函数__readeflags 来完成 - 所以不需要内联汇编(仅适用于 x86) - 接下来的简单代码将在 x86 和 x64 平台上工作:

if (__readeflags() & (1 << 10))
{
    // D flags is set
}

然而在 Windows 上这个标志几乎总是被清除

【讨论】:

  • 谢谢。在我的情况下,这个标志是在 Windows 的 DLL 上使用 STD 设置的
  • @Aviv - Windows 假定此标志始终清除。许多函数使用rep stosX 进行结构初始化或使用rem movsX 进行内存复制,它们不检查此标志,而是假定它为0。如果将其设置为1 - 进程有可能接近100% 崩溃。只有一些功能(如 memove )在短时间内设置此标志而不是清除它
  • @RbMm 我知道 MSDN 在调用其函数时将其列为 MSVC C 标准库的要求,但在任何地方都将其列为 WinAPI ABI 的要求吗?
  • @Anders - 这是 Windows 的标准协议。基于此标志已清除的假设编写的所有 Windows 函数。将其设置为 1 - 您有可能接近 100% 崩溃自己的进程
  • @Ped7g 当然 memmove 将 DF 恢复为 0 如果将其设置为 1 进行反向复制
【解决方案3】:

如果您知道es:edi 指向有效的内存区域并且您不介意修改它(和eax),并且您想要+1/-1 结果而不是0/1:

mov eax,edi
scasb
sub edi,eax   ; edi = +1/-1 for DF=0/1

嗯,有很多 if/and/when 约束,它可能没用(唯一的优点:不需要/修改堆栈)。但是我确实想尝试读取其中一条字符串指令的结果是多么麻烦,因为我在阅读pushf 答案时得到了这个想法。


编辑:堆栈内存变体,通常对读取访问有效(特别是如果其他答案中的pushf 变体有效)(NASM 语法)。

mov esi,esp
ss lodsb      ; size of LODS can change result to +-2 or +-4 (+-8 in 64b)
sub esi,esp   ; esi = +1/-1 for DF = 0/1, does clobber AL
; sets al     ; to get AL = 0/1 for DF = 0/1

【讨论】:

  • 我喜欢这个,因为它避免了pushf 的可怕破坏(它往往与破坏虚拟化的popf 成对出现)。
  • @EOF:它也可以通过改变scas的大小来产生+-2、+-4或+-8的结果。 :D 我不认为这很有用,因为如果您知道 es:edi 指向可读内存,那么您可能对您的运行时环境有足够的了解,也知道当前的 DF 值,我看不到在我自己的代码中使用它。总体而言,除了调试输出之外,为什么要关心 DF 中的内容?您只需根据需要或 ABI 的规定进行设置。
  • 你往往有一个堆栈,所以获得一个指向可读(和可写)内存的指针通常是微不足道的。
  • @EOF ty,修改为“正常工作”,破坏 esi, al,需要有效堆栈(pushf 变体也需要一个,即使未满,这个也适用于满堆栈)。如果有人需要 0/1 结果作为 DF 本身,他可以在 sub 之后执行 sets al
猜你喜欢
  • 1970-01-01
  • 2012-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-13
  • 2019-01-22
  • 1970-01-01
相关资源
最近更新 更多