2008-11-09 5 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 자체가 각 아키텍처마다 다르다는 점을 제외하면 Works 크로스 플랫폼도 마찬가지입니다.

그러나 setjmp (및 어셈블러 코드 호출)를 호출하면 일부 레지스터가 변경되므로 실제로 신뢰할 수는 없습니다.

이 진정한 스냅 샷을 얻을 수있는 방법입니다,하지만 조금 더 어렵고 매우 OS 의존적이다 :

  1. 가 불법 불법 연산 코드 확장에 대한 예외 처리기를 설치합니다. 처리기는 실제 인터럽트, 신호 처리기 또는 OS 예외 처리기 일 수 있습니다 (try/except 블록 형식 C++이 작동하지 않음).

  2. 코드에 잘못된 opcode를 내 보냅니다.

위의 트릭은 잘못된 연산 코드에 레지스터 부작용이 없다는 것입니다. 예외 처리기는 스택 또는 예외 정보 구조에서 레지스터를 복사 할 수 있습니다.

중단 점 인터럽트, 강제 오버플로, 트랩 등으로 동일한 트릭이 작동 할 수 있습니다. 일반적으로 코드 조각에서 인터럽트를 발생시키는 방법은 여러 가지가 있습니다.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 레지스터를 변경하지 않는 코드를 생성하는 아이디어는 있습니까? 일부 푸시의 도움이 될 수 있습니다 ... –

+0

나는 전체 EFLAGS 레지스터를 얻는 것을 고려했다 그러나 그 후에 모든 SH * 정확한 비트를 얻는 것은 계속 진행하고있다. Jcc와 내가 생각하고 있었던 것과 비슷합니다. –

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를 변경하십시오 (pushfq 대신 pushfd 사용). 실제로는 플래그 레지스터에서 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; 
}