在GCC中转储寄存器的值

时间:2008-11-09 09:31:56

标签: gcc assembly x86 ia-32

我需要通过GCC获取寄存器中的值。

类似的东西:

EAX=00000002  EBX=00000001  ECX=00000005  EDX=BFFC94C0
ESI=8184C544  EDI=00000000  EBP=0063FF78  ESP=0063FE3C
CF=0  SF=0  ZF=0  OF=0

获取32位寄存器很简单,但我不确定获取标志的最简单方法是什么。

在本书的示例中:http://kipirvine.com/asm/

他们通过获取整个EFLAGS寄存器并转移相关位来实现。我还想过用Jcc和CMOVcc做的。

关于如何做的任何其他建议?一些要验证的测试用例也很有用。

5 个答案:

答案 0 :(得分:4)

不需要使用汇编程序来获取寄存器。

你可以使用setjmp。这会将所有寄存器写入jmp_buf类型的结构中。除了jmp_buf本身对于每个架构都不同之外,它甚至是一种跨平台的工作。

但是,调用setjmp(并调用汇编代码)会改变一些寄存器,所以你不能真正信任它们。

有一种方法可以获得真正的快照,但这有点困难且高度依赖操作系统:

  1. 为非法非法操作码扩展安装异常处理程序。处理程序可以是实际中断,信号处理程序或OS异常处理程序(C ++的try / except块不起作用)。

  2. 在您的代码中发出非法操作码。

  3. 这里的技巧是,非法操作码没有寄存器副作用。异常处理程序可以从堆栈或异常信息结构中复制寄存器。

    同样的技巧可能适用于断点中断强制溢出,陷阱等。通常有一种方法可以从一段代码中引发中断。


    关于EFLAGS:您可以通过堆栈操作获取它们:

      PUSHFD
      POP EAX  
      , eax now contains the EFLAG data
    

答案 1 :(得分:1)

恕我直言,使用gdb比gcc更好。

http://www.unknownroad.com/rtfm/gdbtut/gdbadvanced.html

HTH

答案 2 :(得分:1)

对64位计算机进行了测试。如果您有32位计算机,请删除64位设备,然后更改flag64 - > flag32(并使用pushfd而不是pushfq)。在实践中,我发现我只需要检查来自标志寄存器的CY(进位)和OV(溢出)(我通常使用jcjncjo和{ {1}})。

jno

答案 3 :(得分:0)

我认为使用Jcc会更长,而不是使用内联汇编。

以下是我目前使用的CMOVcc:

void dump_regs()
{
  int eax = 0;
  int ebx = 0;
  int ecx = 0;
  int edx = 0;

  int esi = 0;
  int edi = 0;
  int ebp = 0;
  int esp = 0;

  int cf = 0;
  int sf = 0;
  int zf = 0;
  int of = 0;

  int set = 1; // -52(%ebp)

  asm( 
    "movl  %eax, -4(%ebp)\n\t"
    "movl  %ebx, -8(%ebp)\n\t"
    "movl  %ecx, -12(%ebp)\n\t"
    "movl  %edx, -16(%ebp)\n\t"
    "movl  %esi, -20(%ebp)\n\t"
    "movl  %edi, -24(%ebp)\n\t"
    "movl  %ebp, -28(%ebp)\n\t"
    "movl  %esp, -32(%ebp)\n\t"

    "movl  $0, %eax\n\t"
    "cmovb -52(%ebp),%eax\n\t" // mov if CF = 1
    "movl  %eax, -36(%ebp) \n\t" // cf

    "movl  $0, %eax\n\t"
    "cmovs -52(%ebp),%eax\n\t" // mov if SF = 1
    "movl  %eax, -40(%ebp)\n\t" // sf

    "movl  $0, %eax\n\t"
    "cmove -52(%ebp),%eax\n\t" // mov if ZF = 1
    "movl  %eax, -44(%ebp)\n\t" // zf

    "movl  $0, %eax\n\t"
    "cmovo -52(%ebp),%eax\n\t" // mov if OF = 1
    "movl  %eax, -48(%ebp)\n\t" // of

    "movl  -4(%ebp), %eax\n\t" // restore EAX
  );

  printf("EAX = %#08x\tEBX = %#08x\tECX = %#08x\tEDX = %#08x\n",eax,ebx,ecx,edx);
  printf("ESI = %#08x\tEDI = %#08x\tEBP = %#08x\tESP = %#08x\n",esi,edi,ebp,esp);
  printf("CF = %d\tSF = %d\tZF = %d\tOF = %d\n",cf,sf,zf,of);
}

我还没有解决的一个重要问题是副作用,我希望能够在不打扰状态的情况下调用它,欢迎任何提示。

答案 4 :(得分:0)

在我的头脑中,如果我错了,请纠正我,但你可以分配一些内存,分配地址,然后用asm括号简单地写入寄存器内容...... 或者你可以把它推入堆栈并以某种方式手动读取它... 我想这需要一些好的asm代码,它可能不是做这样的事情的理想方式,但它会起作用。