<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    HelloWorld 善戰者,求之于勢,不責于人;故能擇人而任勢。

    知止而后有定,定而后能靜,靜而后能安,安而后能慮,慮而后能得。物有本末,事有終始。知所先后,則近道矣。

      BlogJava :: 首頁 ::  :: 聯系 ::  :: 管理 ::
      167 隨筆 :: 1 文章 :: 40 評論 :: 0 Trackbacks

    用cpuid指令讀取CPU信息
    #include <stdio.h>


    int main()
    {
        unsigned int eflags1, eflags2 = 0;
        unsigned int eax = 0;
        unsigned int ebx,ecx,edx;

     


        /**
         * 測試CPU是否支持CPUID指令。
         * eflags寄存器的第21位,如果程序可以清楚/設置它,則說明CPU支持CPUID指令。否則不支持
         */

        /* 先取eflags */
        asm volatile ("pushf\n\t"
                  "popl %%eax"
                  : "=a"(eflags1)
                  :
                  : "memory"
                  );
        printf("original eflags is %p\n", eflags1);

        /* 把eflags的第21位取反,寫回寄存器中 */
        asm volatile ("pushl %0\n\t"
                  "popf"
                  :
                  : "g"(eflags1 & ~( eflags1 & (1<<21) ) )
                  );

        /* 檢查一下現在的eflags,確認第21位和最初的值相反 */
        asm volatile ("pushf\n\t"
                  "popl %%eax"
                  : "=a"(eflags2)
                  :
                  : "memory"
                  );
        printf("modified eflags is %p\n", eflags2);

        /* 把原來的eflags值設置回去 */
        asm volatile ("pushl %0\n\t"
                  "popf"
                  :
                  : "g"(eflags1)
                  );
        /**
         * FIXME: Intel文檔并沒有說,如果不支持CPUID的話,clear/set eflags的第21位會有什么錯誤。
         * 它只說,在不支持CPUID指令的CPU上,如80386,執行CPUID會產生invalid opcode錯誤
         *
         * 所以,在這里我們不處理 讀/寫 eflags 第21比特失敗的情形
         */

     

     

        /**
         *  eax == 1,則在eax中返回Family/Model/Stepping等信息
         *  [0:3]    stepping
         *  [4:7]    model
         *  [8:11]    family
         *  [12:13]    processor type
         *  [16:19]    extended model ID
         *  [20:27]    extended family ID
         */
        asm volatile ("cpuid"
                  : "=a"(eax)
                  : "0"(1)
                  );
        // printf("eax is %p\n", eax);

        printf("Extended Family\t: %d\n", (0xff00000 & eax) >> 20);
        printf("Extended Model\t: %d\n", (0xf0000 & eax) >> 16);
        printf("Processor type\t: %d\n", (0x3000 & eax) >> 12);
        printf("Family\t\t: %d\n", (0xf00 & eax) >> 8);
        printf("Model\t\t: %d\n", (0xf0 & eax) >> 4);
        printf("Stepping:\t: %d\n", (0xf & eax));

        printf("\n");

     

       
        /**
         * eax == 0x800000000
         * 如果CPU支持Brand String,則在EAX中返 >= 0x80000004的值。
         */
        asm volatile ("cpuid"
                  : "=a"(eax)
                  : "0"(0x80000000)
                  );
        printf("Is CPU support Brand String? %s\n", eax >= 0x80000004? "yes":"no");
        printf("\n");

        /**
         * 如果支持Brand String,則EAX從0x80000002到0x80000004,每次增1,CPUID指令返回:
         * EAX    : Processor Brand String
         * EBX    : Processor Brand String Continued
         * ECX    : Processor Brand String Continued
         * EDX    : Processor Brand String Continued
         */

        if(eax >= 0x80000004) {
            unsigned int brands[4]; //每次的eax、ebx、ecx、edx

            unsigned int i;

            printf("Brand String\t: ");

            for (i = 0x80000002; i <= 0x80000004; i++) {
                asm volatile ("cpuid"
                          : "=a"(brands[0]), "=b"(brands[1]), "=c"(brands[2]), "=d"(brands[3])
                          : "0" (i)
                          );
                printf("%s", (char *)brands);
            }

            //FIXME: 打出來的字符串是:In^Htel(R) Pentium(R^H) D CPU 2.80GHz

            //其中^H是個不可見字符,會把它前一個吃掉

            printf("\n");
        }

     

        /**
         * eax == 0
         * eax    : cpuid指令允許的最大eax輸入值
         * ebx    : "Genu"
         * ecx    : "ntel"
         * edx    : "inel"
         */
        asm volatile ("cpuid"
                  : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
                  : "0"(0) );
        printf("Maximum CPUID Input EAX : %p\n", eax);


        char string[128];
        snprintf(string, 5, "%s", (char *)&ebx);
        snprintf(string + 4, 5, "%s", (char *)&edx);
        snprintf(string + 8, 5, "%s", (char *)&ecx);
        printf("Vendor\t\t: %s\n", string);

        printf("\n");


        /**
         * eax == 1,
         * edx的第18比特為1,則CPU支持serial number
         *         為0,則不支持,或者被disabled
         * 序列號有96位,其中最高32位即是eax的輸出值。應當把它保存下來,然后
         * 再設置eax==3, 取剩下的64位
         */
        asm volatile ("cpuid"
                  : "=a"(eax), "=d"(edx)
                  : "a"(1)
                  );
        if ( edx & (1 << 18) ) {
            /* serial number supported */
            /* edx輸出中間32位的序列號,ecx輸出最低32位的序列號 */
            asm volatile ("cpuid"
                      : "=c"(ecx), "=d"(edx)
                      : "a"(3)
                      );
            printf("Serial Number\t : %x-%x-%x-%x-%x-%x\n",
                    eax >> 16, eax << 16, edx >> 16, edx << 16, ecx >> 16, ecx << 16);
        } else
            printf("Serial Number not supported.\n");

        printf("\n");


        /**
         * eax == 80000006h,返回L2 Cache的信息
         *
         * ecx[31:16]    : L2 Cache size, in Kbytes
         * ecx[15:12]    : L2 Cache Associativity
         *           00h disabled
         *           01h direct mapped
         *           02h 2-Way
         *           04h 4-Way
         *           06h 8-Way
         *           08h 16-Way
         *           0Fh Fully associative
         * ecx[7:0]    : L2 Cache Line size in bytes
         */
        asm volatile ("cpuid"
                  : "=c"(ecx)
                  : "a"(0x80000006)
                  );
        printf("L2 Cache Size\t : %dKbytes\n", ( ecx >> 16 ) );
        printf("L2 Cache Line Size\t : %dbytes\n", (ecx & 0xff));

        printf("L2 Cache Associativity\t : ");
        switch ( (ecx & 0xf000) >> 12 )
        {
            case 0x00:
                printf("%s\n", "disabled");
                break;
            case 0x01:
                printf("%s\n", "direct mapped");
                break;
            case 0x02:
                printf("%s\n", "2-Way");
                break;
            case 0x04:
                printf("%s\n", "4-Way");
                break;
            case 0x06:
                printf("%s\n", "8-Way");
                break;
            case 0x08:
                printf("%s\n", "16-Way");
                break;
            case 0x0f:
                printf("Fully associative");
                break;
            default:
                printf("No such entry...\n");
        }

        printf("\n");


        /**
         * Input : eax == 4 && ecx == 0
         *
         * (eax[31:26] + 1) 是該物理處理器package上實現的core CPUs數目
         */
        asm volatile ("cpuid"
                  : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
                  : "0"(4), "2"(0)
                  );
        printf("Number of Cores on this physical package\t : %d\n", (eax >> 27) + 1 );

        printf("\n");


        /**
         * Input : eax == 1,則edx返回feature flag
         *
         */

     

     

        return 0;
    }



    </script>

    posted on 2007-10-24 15:04 helloworld2008 閱讀(2395) 評論(0)  編輯  收藏 所屬分類: Linux/C
    主站蜘蛛池模板: 久久精品一本到99热免费| 久久这里只精品99re免费| 成人免费男女视频网站慢动作| 婷婷久久久亚洲欧洲日产国码AV| 国产黄片不卡免费| 亚洲日本乱码在线观看| 全黄大全大色全免费大片| 亚洲日韩欧洲乱码AV夜夜摸| 中国一级特黄的片子免费| 亚洲第一AAAAA片| 99视频在线看观免费| 亚洲人成电影在线观看网| 国产成人免费高清激情明星| 亚洲人妖女同在线播放| 成年在线网站免费观看无广告 | 免费精品国产日韩热久久| 亚洲免费一级视频| 国产成人青青热久免费精品| 四虎影视永久在线精品免费| 亚洲精品乱码久久久久久蜜桃不卡| 丁香花在线视频观看免费 | 亚洲中文字幕在线观看| a在线观看免费网址大全| 亚洲卡一卡2卡三卡4卡无卡三| 免费黄色网址网站| 99亚洲精品卡2卡三卡4卡2卡| 国产日产亚洲系列最新| 未满十八18禁止免费无码网站 | 精品久久久久久久久亚洲偷窥女厕| 国产精品无码一区二区三区免费 | 亚洲youjizz| 又黄又爽无遮挡免费视频| 国产一区二区三区免费观看在线| 亚洲视频免费观看| 日日操夜夜操免费视频| 99精品免费视品| 亚洲综合偷自成人网第页色| 亚洲色婷婷综合开心网| 1区2区3区产品乱码免费| 美女的胸又黄又www网站免费| 日本红怡院亚洲红怡院最新|