<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 閱讀(2385) 評論(0)  編輯  收藏 所屬分類: Linux/C
    主站蜘蛛池模板: 国内外成人免费视频| 国精产品一区一区三区免费视频| 精品无码AV无码免费专区| 国产亚洲av片在线观看播放| 日本一区二区三区免费高清在线| 国产免费观看a大片的网站| 午夜亚洲国产精品福利| 一区二区三区亚洲视频| fc2成年免费共享视频网站| 亚洲综合AV在线在线播放| 免费国产叼嘿视频大全网站 | 免费国产成人18在线观看| 亚洲一级二级三级不卡| 久久精品无码专区免费青青| 亚洲日韩国产精品无码av| 女人18一级毛片免费观看| 美女18一级毛片免费看| 亚洲精品自产拍在线观看| 91香蕉在线观看免费高清| 亚洲一级毛片免费看| 日本视频免费在线| 国产一级黄片儿免费看| 久久久无码精品亚洲日韩蜜臀浪潮 | 女人18一级毛片免费观看| 色视频在线观看免费| 亚洲精品国产美女久久久| 3344永久在线观看视频免费首页| 亚洲AV日韩综合一区尤物| 亚洲国产日韩成人综合天堂| 国产在线观看免费视频软件 | 777亚洲精品乱码久久久久久| 日韩国产免费一区二区三区| 亚洲成AV人影片在线观看| 亚洲精品午夜无码专区| 在线看免费观看AV深夜影院| 男男gvh肉在线观看免费| 亚洲欧洲在线观看| 免费人成在线观看网站品爱网日本| 天黑黑影院在线观看视频高清免费| 亚洲精品中文字幕无乱码| 亚洲第一区精品日韩在线播放|