Read flag register from C program

assembly, c, flags, x86

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;

Problem

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" ```

Original source

Related problems