2008-11-09 84 views
3

我需要使用GCC获取寄存器中的值。转储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做它。

有关如何做到这一点的其他建议?一些要验证的测试用例也是有用的。

回答

4

没有必要使用汇编器来获取寄存器。

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

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

有一种方式来获得一个真正的快照,但是这是一个有点难度,高度依赖于操作系统的:

  1. 安装一个异常处理程序非法违法码扩展。处理程序可以是一个真正的中断,一个信号处理程序或一个操作系统异常处理程序(try/except块形式的C++将不起作用)。

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

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

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


关于EFLAGS:您可以通过一个栈的操作让他们:

PUSHFD 
    POP EAX 
    , eax now contains the EFLAG data 
+0

如何从jmp_buf结构中重建寄存器并不是很清楚。我在这里找到它的源代码: http://ccrma.stanford.edu/courses/250a/docs/avrgcc/setjmp_8h-source.html 生产不改变寄存器的代码的任何想法?有些PUSH可以帮助... – 2008-11-09 17:55:17

+0

我认为得到整个EFLAGS寄存器,但所有SH *得到正确的位会使它不清楚发生了什么。类似于我想要用Jcc做的事情。 – 2008-11-09 17:57:13

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); 
} 

一个重要的事情我还没有制定出尚未有副作用,我希望能够把这种无干扰状态下,任何在这方面的提示是受欢迎的。

0

在我的头顶,纠正我,如果我错了,但你可以只分配一些内存,分配地址,并简单地写在那里的寄存器内容与asm括号... 或你可以将它推入堆栈并以某种方式手动读取它... 我想这需要一些很好的asm代码,它可能不是执行此类操作的理想方式,但它会起作用。

1

的后续是为一个64位的机测试。如果您有32位机器,请删除64位齿轮,然后更改flag64 - > flag32(并使用pushfd而不是pushfq)。实际上,我发现我只需要检查标志寄存器中的CY(进位)和OV(溢出)(我通常使用jc,jnc,jojno进行检测)。

#include <stdio.h> 
#include <stdint.h> 

#define HIGH32(x) ((uint32_t)(((uint64_t)x)>>32)) 
#define LOW32(x) ((uint32_t)(((uint64_t)x)& 0xFFFFFFFF)) 

int main(int argc, char** argv) 
{ 
    uint32_t eax32, ebx32, ecx32, edx32; 
    uint64_t rax64, rbx64, rcx64, rdx64; 

    asm (
     "movl %%eax, %[a1] ;" 
     "movl %%ebx, %[b1] ;" 
     "movl %%ecx, %[c1] ;" 
     "movl %%edx, %[d1] ;" 

     "movq %%rax, %[a2] ;" 
     "movq %%rbx, %[b2] ;" 
     "movq %%rcx, %[c2] ;" 
     "movq %%rdx, %[d2] ;" 
     : 
     [a1] "=m" (eax32), [b1] "=m" (ebx32), [c1] "=m" (ecx32), [d1] "=m" (edx32), 
     [a2] "=m" (rax64), [b2] "=m" (rbx64), [c2] "=m" (rcx64), [d2] "=m" (rdx64) 
     ); 

    printf("eax=%08x\n", eax32); 
    printf("ebx=%08x\n", ebx32); 
    printf("ecx=%08x\n", ecx32); 
    printf("edx=%08x\n", edx32); 

    printf("rax=%08x%08x\n", HIGH32(rax64), LOW32(rax64)); 
    printf("bax=%08x%08x\n", HIGH32(rbx64), LOW32(rbx64)); 
    printf("cax=%08x%08x\n", HIGH32(rcx64), LOW32(rcx64)); 
    printf("dax=%08x%08x\n", HIGH32(rdx64), LOW32(rdx64)); 

    uint64_t flags; 

    asm (
     "pushfq  ;" 
     "pop %[f1] ;" 
     : 
     [f1] "=m" (flags) 
     ); 

    printf("flags=%08x%08x", HIGH32(flags), LOW32(flags)); 

    if(flags & (1 << 0)) // Carry 
     printf(" (C1"); 
    else 
     printf(" (C0"); 

    if(flags & (1 << 2)) // Parity 
     printf(" P1"); 
    else 
     printf(" P0"); 

    if(flags & (1 << 4)) // Adjust 
     printf(" A1"); 
    else 
     printf(" A0"); 

    if(flags & (1 << 6)) // Zero 
     printf(" Z1"); 
    else 
     printf(" Z0"); 

    if(flags & (1 << 7)) // Sign 
     printf(" S1"); 
    else 
     printf(" S0"); 

    if(flags & (1 << 11)) // Overflow 
     printf(" O1)\n"); 
    else 
     printf(" O0)\n"); 

    return 0; 
}