在GCC中转储寄存器的值

在GCC中转储寄存器的值,gcc,assembly,x86,Gcc,Assembly,X86,我需要用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 EAX=00000002 EBX=00000001 ECX=00000005 EDX=BFFC94C0 ESI=8184C544 EDI=00000000 EBP=0063FF78 ESP=

我需要用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 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位寄存器很容易,但我不确定获取标志的最简单方法是什么

在本书的示例中:

他们通过获取整个EFLAGS寄存器并对所讨论的位进行移位来实现。我还考虑过使用Jcc和CMOVcc


还有其他建议吗?一些要验证的测试用例也会很有用。

我认为使用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); } 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” “移动%ebx,-8(%ebp)\n\t” “移动%ecx,-12(%ebp)\n\t” “移动%edx,-16(%ebp)\n\t” “移动%esi,-20(%ebp)\n\t” “移动%edi,-24(%ebp)\n\t” “移动%ebp,-28(%ebp)\n\t” “移动%esp,-32(%ebp)\n\t” movl$0,%eax\n\t “cmovb-52(%ebp),%eax\n\t”//mov,如果CF=1 “移动%eax,-36(%ebp)\n\t”//cf movl$0,%eax\n\t “cmovs-52(%ebp),%eax\n\t”//mov,如果SF=1 “移动%eax,-40(%ebp)\n\t”//sf movl$0,%eax\n\t “cmove-52(%ebp),%eax\n\t”//mov,如果ZF=1 “movl%eax,-44(%ebp)\n\t”//zf movl$0,%eax\n\t “cmovo-52(%ebp),%eax\n\t”//mov如果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); }
有一件重要的事情我还没有弄清楚,那就是副作用,我希望能够在不干扰状态的情况下,称之为副作用,欢迎任何这方面的建议。

我的头顶,如果我错了,请纠正我,但你可以分配一些内存,分配地址,然后简单地用一个asm括号将寄存器内容写入其中。。。 或者你可以把它推到堆栈中,以某种方式手动读取。。。
我想这需要一些好的asm代码,这可能不是实现类似操作的理想方法,但它会工作。

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

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

然而,调用setjmp(以及调用汇编代码)会改变一些寄存器,因此您不能真正信任它们

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

  • 为非法操作码扩展安装异常处理程序。处理程序可以是真正的中断、信号处理程序或OS异常处理程序(尝试/不包括块的形式C++将不工作)。p>
  • 在代码中发出非法操作码

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

    同样的技巧也适用于断点中断、强制溢出、陷阱等。从一段代码中引发中断的方法通常不止一种


    关于EFLAG:您可以通过堆栈操作获得它们:

      PUSHFD
      POP EAX  
      , eax now contains the EFLAG data
    

    IMHO,使用gdb比gcc更好


    HTH

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

    #包括
    #包括
    #定义高32(x)((uint32_t)((uint64_t)x)>>32))
    #定义LOW32(x)((uint32_t)((uint64_t)x)和0xffffff))
    int main(int argc,字符**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”、高32(rax64)、低32(rax64));
    printf(“bax=%08x%08x\n”、高32(rbx64)、低32(rbx64));
    printf(“cax=%08x%08x\n”、高32(rcx64)、低32(rcx64));
    printf(“dax=%08x%08x\n”、高32(rdx64)、低32(rdx64));
    uint64_t标志;
    asm(
    “pushfq;”
    “pop%[f1];”
    :
    [f1]“=m”(标志)
    );
    printf(“标志=%08x%08x”、高32(标志)、低32(标志));
    
    如果(旗帜,(1)不太清楚如何从jmp_buf结构中重建寄存器。我在这里找到了它的来源:在生成不改变寄存器的代码时有什么想法吗?一些推送可能会有所帮助…我考虑过获得整个EFLAGS寄存器,但是所有的SH*获得正确的位会让它不太清楚发生了什么。类似于wha我正在考虑使用Jcc的。这很有用!它帮助我验证了我所做的是正确的。谢谢!
    #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;
    }