2008-11-09 18 views
3

J'ai besoin d'obtenir les valeurs dans les registres avec GCC.Déposer les valeurs des registres dans GCC

Quelque chose de semblable à ceci:

 
EAX=00000002 EBX=00000001 ECX=00000005 EDX=BFFC94C0 
ESI=8184C544 EDI=00000000 EBP=0063FF78 ESP=0063FE3C 
CF=0 SF=0 ZF=0 OF=0 

Obtenir les registres assez facile 32 bits, mais je ne suis pas sûr de ce que la façon la plus simple d'obtenir les drapeaux est.

Dans les exemples de ce livre: http://kipirvine.com/asm/

Ils le font en obtenant tout le registre de EFLAGS et de décalage pour le bit en question. J'ai aussi pensé à le faire en utilisant Jcc et CMOVcc.

D'autres suggestions sur la façon de le faire? Certains cas de test à vérifier seraient également utiles.

Répondre

4

Il n'est pas nécessaire d'utiliser l'assembleur uniquement pour obtenir les registres.

Vous pouvez simplement utiliser setjmp. Cela écrira tous les registres dans une structure de type jmp_buf. Il fonctionne même comme une plate-forme croisée, sauf pour le fait que jmp_buf lui-même est différent pour chaque architecture. Cependant, appeler setjmp (et appeler aussi votre code assembleur) changera certains des registres, donc vous ne pouvez pas vraiment leur faire confiance.

Il est un moyen d'obtenir un vrai cliché, mais qui est un peu plus difficile et dépend fortement OS:

  1. installer un gestionnaire d'exception pour l'extension illégale opcode illégale. Le gestionnaire peut être une véritable interruption, un gestionnaire de signal ou un gestionnaire d'exception OS (le bloc try/except former C++ ne fonctionnera pas).

  2. Emettez un code d'opération illégal dans votre code.

L'astuce ici est, que l'opcode illégal n'a pas d'effets secondaires de registre. Le gestionnaire d'exceptions peut copier les registres à partir de la pile ou à partir d'une structure d'informations d'exception.

La même astuce peut fonctionner avec les interruptions de point d'arrêt des débordements forcés, des pièges ou plus. Il y a généralement plus d'une façon de déclencher une interruption à partir d'un morceau de code.


En ce qui concerne les EFLAGS: vous pouvez les obtenir via une opération de pile:

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

Il est pas très clair comment reconstituer les registres de la struct jmp_buf. J'ai trouvé la source pour cela ici: http://ccrma.stanford.edu/courses/250a/docs/avrgcc/setjmp_8h-source.html Des idées dans la production de code qui ne change pas les registres? Quelques PUSH pourraient aider ... –

+0

J'ai considéré obtenir le registre entier d'EFLAGS mais alors tout le SH * pour obtenir le bon morceau rendrait moins clair ce qui se passe. Semblable à ce que je pensais faire avec Jcc. –

0

Je pense que l'utilisation de Jcc serait plus longue et moins claire avec l'assemblage en ligne.

Voici ce que j'ai actuellement, en utilisant CMOVcc de:

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

Une chose importante que je ne l'ai pas élaboré encore sont les effets secondaires, je veux être en mesure d'appeler cela sans déranger l'état, tout Les conseils dans cette direction sont les bienvenus.

0

Du haut de ma tête, et corrigez-moi si je me trompe, mais vous pouvez juste allouer de la mémoire, obtenir l'adresse allouée, et simplement écrire le contenu du registre là-bas avec un support ASM ... vous pourriez juste le pousser dans la pile et le lire manuellement d'une manière ou d'une autre ... Je suppose que cela prendrait du bon code asm et ce n'est probablement pas la façon idéale de faire quelque chose comme ça, mais ça marchera.

1

Le suivi a été testé pour une machine 64 bits. Si vous avez une machine 32 bits, supprimez l'engrenage 64 bits et changez flag64 -> flag32 (et utilisez pushfd au lieu de pushfq). En pratique, je trouve que j'ai seulement besoin d'inspecter CY (carry) et OV (overflow) du registre des drapeaux (et je le fais habituellement avec jc, jnc, jo, et 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; 
}