【发布时间】:2017-07-25 11:06:28
【问题描述】:
我正在尝试从 EFLAGS 寄存器中获取 DF 的值。
我尝试使用 LAHF 指令,但根据 Intel X86 文档,该指令仅加载 SF, ZF, AF, PF, CF 标志。但是,我正在尝试找到一条指令,它可以为我提供 DF 寄存器的值。
提前致谢。
【问题讨论】:
-
pushf然后检查堆栈。
标签: c windows debugging assembly x86
我正在尝试从 EFLAGS 寄存器中获取 DF 的值。
我尝试使用 LAHF 指令,但根据 Intel X86 文档,该指令仅加载 SF, ZF, AF, PF, CF 标志。但是,我正在尝试找到一条指令,它可以为我提供 DF 寄存器的值。
提前致谢。
【问题讨论】:
pushf 然后检查堆栈。
标签: c windows debugging assembly x86
使用以下代码:
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。
pushf ; test byte [esp+1],4 ; add esp, 4。或者下次需要调整堆栈时弹出。
pushf; test byte [esp+1],4 ; lea esp, [esp+4] 测试结果仍然可用。
这也可以使用内部函数__readeflags 来完成 - 所以不需要内联汇编(仅适用于 x86) - 接下来的简单代码将在 x86 和 x64 平台上工作:
if (__readeflags() & (1 << 10))
{
// D flags is set
}
然而在 Windows 上这个标志几乎总是被清除
【讨论】:
rep stosX 进行结构初始化或使用rem movsX 进行内存复制,它们不检查此标志,而是假定它为0。如果将其设置为1 - 进程有可能接近100% 崩溃。只有一些功能(如 memove )在短时间内设置此标志而不是清除它
如果您知道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 成对出现)。
scas的大小来产生+-2、+-4或+-8的结果。 :D 我不认为这很有用,因为如果您知道 es:edi 指向可读内存,那么您可能对您的运行时环境有足够的了解,也知道当前的 DF 值,我看不到在我自己的代码中使用它。总体而言,除了调试输出之外,为什么要关心 DF 中的内容?您只需根据需要或 ABI 的规定进行设置。
esi, al,需要有效堆栈(pushf 变体也需要一个,即使未满,这个也适用于满堆栈)。如果有人需要 0/1 结果作为 DF 本身,他可以在 sub 之后执行 sets al。