Search code examples
cassemblyx86flags

Read flag register from C program


For the sake of curiosity I'm trying to read the flag register and print it out in a nice way.

I've tried reading it using gcc's asm keyword, but i can't get it to work. Any hints how to do it? I'm running a Intel Core 2 Duo and Mac OS X. The following code is what I have. I hoped it would tell me if an overflow happened:

#include <stdio.h>

int main (void){
  int a=10, b=0, bold=0;
  printf("%d\n",b);
  while(1){
    a++;
  __asm__ ("pushf\n\t"
   "movl 4(%%esp), %%eax\n\t"
   "movl %%eax , %0\n\t"
   :"=r"(b)      
   :         
   :"%eax"        
   ); 
  if(b!=bold){ 
    printf("register changed \n %d\t to\t %d",bold , b);
  }
  bold = b;
  }
}

This gives a segmentation fault. When I run gdb on it I get this:

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x000000005fbfee5c
0x0000000100000eaf in main () at asm.c:9
9       asm ("pushf \n\t"

Solution

  • You can use the PUSHF/PUSHFD/PUSHFQ instruction (see http://siyobik.info/main/reference/instruction/PUSHF%2FPUSHFD for details) to push the flag register onto the stack. From there on you can interpret it in C. Otherwise you can test directly (against the carry flag for unsigned arithmetic or the overflow flag for signed arithmetic) and branch.

    (to be specific, to test for the overflow bit you can use JO (jump if set) and JNO (jump if not set) to branch -- it's bit #11 (0-based) in the register)

    About the EFLAGS bit layout: http://en.wikibooks.org/wiki/X86_Assembly/X86_Architecture#EFLAGS_Register

    A very crude Visual C syntax test (just wham-bam / some jumps to debug flow), since I don't know about the GCC syntax:

    int test2 = 2147483647; // max 32-bit signed int (0x7fffffff)
    unsigned int flags_w_overflow, flags_wo_overflow;
    __asm
    {
        mov ebx, test2 // ebx = test value
    
        // test for no overflow
        xor eax, eax // eax = 0
        add eax, ebx // add ebx
        jno no_overflow // jump if no overflow
    
    testoverflow:
        // test for overflow
        xor ecx, ecx // ecx = 0
        inc ecx // ecx = 1
        add ecx, ebx // overflow!
        pushfd // store flags (32 bits)
        jo overflow // jump if overflow
        jmp done // jump if not overflown :(
    
    no_overflow:
        pushfd // store flags (32 bits)
        pop edx // edx = flags w/o overflow
        jmp testoverflow // back to next test
    
    overflow:
        jmp done // yeah we're done here :)
    
    done:
        pop eax // eax = flags w/overflow
        mov flags_w_overflow, eax // store
        mov flags_wo_overflow, edx // store
    }
    
    if (flags_w_overflow & (1 << 11)) __asm int 0x3 // overflow bit set correctly
    if (flags_wo_overflow & (1 << 11)) __asm int 0x3 // overflow bit set incorrectly
    
    return 0;