Сброс значений из регистров в 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.

Любые другие предложения о том, как это сделать? Некоторые контрольные примеры для проверки также были бы полезны.

5 ответов

Решение

Нет необходимости использовать ассемблер только для получения регистров.

Вы можете просто использовать setjmp. Это запишет все регистры в структуру типа jmp_buf. Это даже своего рода кроссплатформенность Works за исключением того факта, что сам jmp_buf отличается для каждой архитектуры.

Однако, вызов setjmp (и вызов вашего ассемблерного кода) изменит некоторые регистры, поэтому вы не можете им доверять.

Есть способ получить настоящий снимок, но это немного сложнее и сильно зависит от операционной системы:

  1. установите обработчик исключений для нелегального нелегального расширения кода операции. Обработчик может быть либо действительным прерыванием, обработчиком сигнала, либо обработчиком исключений ОС (блоки try/ исключением из формы C++ не будут работать).

  2. Создайте недопустимый код операции в вашем коде.

Хитрость в том, что нелегальный код операции не имеет побочных эффектов. Обработчик исключений может копировать регистры либо из стека, либо из информационной структуры исключения.

Тот же трюк может работать с прерываниями точки останова, принудительными переполнениями, ловушками и т. Д. Обычно существует более одного способа вызвать прерывание из фрагмента кода.


Относительно EFLAGS: Вы можете получить их через операцию стека:

  PUSHFD
  POP EAX  
  , eax now contains the EFLAG data

Последующее было протестировано на 64-битной машине. Если у вас 32-битный компьютер, удалите 64-битную передачу и измените flag64 -> flag32 (и используйте pushfd вместо pushfq). На практике я нахожу, что мне нужно только проверять CY (перенос) и OV (переполнение) из регистра флагов (и я обычно делаю это с jc, jnc, jo, а также jno).

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

ИМХО, использование GDB лучше, чем GCC.

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

НТН

Из головы, и поправьте меня, если я ошибаюсь, но вы можете просто выделить немного памяти, выделить адрес и просто записать туда содержимое регистра с помощью скобки asm... Или вы можете просто нажать ее в стек и как-то читать его вручную... Я думаю, что потребуется хороший ассемблерный код, и это, вероятно, не идеальный способ сделать что-то подобное, но это будет работать.

Я думаю, что использование 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)

  как м("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, если CF = 1
    "movl% eax, -36 (% ebp) \ n \ t" // cf

    "movl $ 0,% eax \ n \ t"
    "cmovs -52 (% ebp),% eax \ n \ t" // mov, если SF = 1
    "movl% 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 if OF = 1
    "movl% eax, -48 (% ebp) \ n \ t" // из

    "movl  -4(%ebp), %eax\n\t" // восстановить 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);
}

Одна важная вещь, которую я еще не разработал, - это побочные эффекты, я хочу, чтобы это можно было назвать, не нарушая состояние, любые советы в этом направлении приветствуются.

Другие вопросы по тегам