Сброс значений регистров в GCC - PullRequest
3 голосов
/ 09 ноября 2008

Мне нужно получить значения в регистрах с 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 ]

4 голосов
/ 09 ноября 2008

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

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

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

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

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

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

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

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


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

  PUSHFD
  POP EAX  
  , eax now contains the EFLAG data
1 голос
/ 20 июня 2011

Следующее было протестировано для 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;
}
1 голос
/ 09 ноября 2008

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

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

НТН

0 голосов
/ 09 ноября 2008

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

0 голосов
/ 09 ноября 2008

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

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

...