读取C程序标志寄存器 [英] Read flag register from C program

查看:330
本文介绍了读取C程序标志寄存器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有关好奇的缘故,我要看书标志寄存器,并打印出一个不错的方式。

我试过用gcc的 ASM 关键字读它,但我不能得到它的工作。任何提示怎么办呢?我跑了英特尔酷睿2双核和Mac OS X下code是我。我希望它会告诉我,如果溢出发生了:

 的#include<&stdio.h中GT;诠释主要(无效){
  诠释A = 10,B = 0,大胆= 0;
  的printf(%d个\\ N,B);
  而(1){
    一个++;
  __asm​​__(PUSHF \\ n \\ t的
   MOVL 4(%% ESP),EAX %% \\ n \\ t的
   MOVL EAX %%,%0 \\ n \\ t的
   := R(二)
   :
   :%EAX
   );
  如果(B!=黑体){
    的printf(登记变更\\ n%d个\\吨至\\ T%D,大胆,二);
  }
  大胆= B;
  }
}

这给出了一个分段错误。当我在其上运行gdb的,我得到这样的:

 程序接收到的信号EXC_BAD_ACCESS,无法访问内存。
原因:KERN_INVALID_ADDRESS地址:0x000000005fbfee5c
0x0000000100000eaf在main()在asm.c:9
9 ASM(PUSHF \\ n \\ t的


解决方案

您可以使用PUSH​​F / PUSHFD / PUSHFQ指令(见的 http://siyobik.info/main/reference/instruction/PUSHF%2FPUSHFD 了解详细信息)推标志寄存器压入堆栈。从那里,你可以跨preT它C.否则,您可以直接测试(针对无符号运算或符号算术溢出标志进位标志)和分支。

(要具体,要测试你可以使用JO(跳跃如果已设置)和JNO(跳跃如果没有设置)分支溢出位 - 这是位#11(从0开始)在寄存器)

关于EFLAGS位布局: http://en.wikibooks.org/wiki/ X86_Assembly / X86_Architecture#EFLAGS_Register

一个非常粗略的Visual C语法测试(只重打-BAM /跳跃的一些调试流量),因为我不知道有这个GCC语法信息:

 内部测试2 = 2147483647; //最多32位有符号整数(为0x7FFFFFFF)
unsigned int类型flags_w_overflow,flags_wo_overflow;
__asm
{
    MOV EBX,TEST2 // EBX =测试值    //测试没有溢出
    XOR EAX,EAX // EAX = 0
    添加EAX,EBX //添加EBX
    JNO no_overflow //跳跃,如果没有溢出testoverflow:
    //测试溢出
    异或ECX,ECX // ECX = 0
    INC ECX // ECX = 1
    加ECX,EBX //溢出!
    PUSHFD //商店标志(32位)
    乔溢出//如果跳溢出
    JMP做//跳转如果不是飞越:(no_overflow:
    PUSHFD //商店标志(32位)
    弹出EDX // EDX =标志W / O溢出
    JMP testoverflow //返回到下一个测试溢出:
    JMP做//是啊,我们要在这里完成:)完成:
    流行EAX // EAX =标志W /溢出
    MOV flags_w_overflow,EAX //店
    MOV flags_wo_overflow,EDX //店
}如果(flags_w_overflow及(1 LT;< 11))__asm​​ INT 0x3中//溢出位设置正确
如果(flags_wo_overflow及(1 LT;< 11))__asm​​ INT 0x3中//溢出位设置不正确返回0;

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"

解决方案

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;

这篇关于读取C程序标志寄存器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆