2

我正在尝试学习如何编写和理解x86 Assembly以及如何GDB有效地使用和相关工具。为此,我将DDD其用作GDB.

我无法理解条件标志(eflags?)的含义,因为它们似乎都存储在同一个寄存器中。我将发布寄存器、汇编代码和相关的 C 代码。感谢您提供任何帮助。

寄存器在给定断点处显示如下:0x293 [CF AF SF IF]

以下是正在运行的 C 代码。(这不是我编码风格的示例。我试图强制 GCC 使用该compl操作。)

int main( int argc, char* argv[] )
{
  int a = 0;
  int b = 2;
  if( a == b ) // There is a breakpoint here!
    goto EQUAL;
  else
    goto NEQUAL;

  EQUAL:
    return 3;

  NEQUAL:
    return 1;
}

以下是我的机器将其分解成的组件:

Dump of assembler code for function main:
0x0000000000400474 <+0>:     push   %rbp
0x0000000000400475 <+1>:     mov    %rsp,%rbp
0x0000000000400478 <+4>:     mov    %edi,-0x14(%rbp)
0x000000000040047b <+7>:     mov    %rsi,-0x20(%rbp)
0x000000000040047f <+11>:    movl   $0x0,-0x8(%rbp)
0x0000000000400486 <+18>:    movl   $0x2,-0x4(%rbp)
0x000000000040048d <+25>:    mov    -0x8(%rbp),%eax
0x0000000000400490 <+28>:    cmp    -0x4(%rbp),%eax
0x0000000000400493 <+31>:    jne    0x40049d <main+41> # Break point here
0x0000000000400495 <+33>:    nop
0x0000000000400496 <+34>:    mov    $0x3,%eax
0x000000000040049b <+39>:    jmp    0x4004a3 <main+47>
0x000000000040049d <+41>:    nop
0x000000000040049e <+42>:    mov    $0x1,%eax
0x00000000004004a3 <+47>:    leaveq 
0x00000000004004a4 <+48>:    retq   
End of assembler dump.
4

2 回答 2

3

eflags 寄存器由单个位组成,每个位都是一个标志。

显示标志时,它们可以组合成一个更大的数字实体(例如您的示例中的 0x293),或者每个都可以有自己的符号(例如在带有进位标志 CF 的“[CF AF SF IF]”中,调整标志AF、符号标志SF和中断标志IF。

英特尔64 和 IA 32 架构软件开发人员手册卷。1在第 3.4.3 章中详细描述了这些标志。

最重要的(对于应用程序开发人员)是:

位 | 符号 | 姓名
------------------
  0 | CF | 携带
  1 | -- | (总是 1)
  2 | PF | 平价
  3 | -- | (总是 0)
  4 | 自动对焦 | 调整
  5 | -- | (总是 0)
  6 | 采埃孚 | 零
  7 | 顺丰 | 符号
  8 | TF | 陷阱
  9 | 中频 | 打断
 10 | 东风 | 方向
 11 | 的 | 溢出

结合你的例子中的那些(CF AF SF IF)给出二进制值1010010011,其中最右边的数字是进位标志,最左边的数字是中断标志。转换为十六进制它正好给出 0x293。

于 2012-09-12T20:40:43.633 回答
2

(R/E)FLAGS寄存器包含以下条件标志:

OF(溢出标志) - 它用于确定有符号操作数上整数算术运算(例如,、、、ADD指令)ADCSUB溢出。SBB条件分支/跳转(Jcc指令)可以直接检查这个标志。

SF(符号标志) - 用于确定最后一个整数算术运算的结果是否为负值,SF基本上是结果的符号位(=最高有效位)的副本。同样,条件分支/跳转可以直接检查它。

ZF(零标志) - 用于确定最后一个整数算术或逻辑运算的结果是否为 0。条件分支/跳转也可以直接检查它。

CF (进位标志) - 与溢出标志 ( OF )类似,它可用于确定对无符号操作数执行的整数算术运算的溢出。注意区别:CF代表无符号,OF代表有符号。另请注意,CPU 通常会计算 CFOF,程序员有责任检查正确的标志。在大多数情况下,CPU 不能也不会区分有符号和无符号操作数,因为结果是以相同的方式计算的,而且它都是 CPU 的数据。将值解释为有符号或无符号是程序员的职责,而不是 CPU 的职责。条件分支/跳转也可以直接检查CF。

编辑:还有使用CFrotate through carry的指令(RCLRCR)。

整数比较(与CMP指令)导致上述四个标志集。如果您打算比较无符号整数,请检查ZF和/或CF。对于有符号整数比较,您需要检查ZF和/或SF + OF对。请参阅条件分支/跳转指令(Jcc: JB, JNC, JE, JNGE, 等)。

奇偶校验标志PF和辅助进位标志AF是其他条件标志,但它们很少使用。

中的其余位(R/E)FLAGS要么是系统标志,要么是控制标志。其中你可能只想知道两个:

DF(方向标志)——用于设置字符串指令的方向。字符串指令用于顺序访问内存,例如块内存复制、块内存比较、块内存搜索、块内存填充(参见MOVSB/W/D/Q, CMPSB/W/D/Q, SCASB/W/D/Q, STOSB/W/D/Q, LODSB/W/D/Q)。这个标志的值告诉内存操作数地址是在每次迭代后递增还是递减。

IF(中断标志) - 它用于启用或禁用硬件中断处理。如果您进入非常低级的编程(驱动程序、操作系统内核等),您将不得不使用此标志。

就是这样。英特尔和 AMD 的官方 CPU 文档中提供了所有详细信息。去,下载CPU手册。

编辑:您可能会发现这些问题/答案很有用:12

同样有用的是:

  • 并非所有指令都会修改条件标志
  • 有些人总是修改它们并设置为 0 或 1
  • 有些将它们设置为未指定的值,您不能依赖或期望 0 或 1
于 2012-09-12T20:53:22.513 回答