<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
    主站蜘蛛池模板: 亚洲精品久久无码| 特级毛片免费播放| 精品久久久久久久久免费影院| 亚洲VA成无码人在线观看天堂| eeuss草民免费| 亚洲精品国产精品国自产观看| 久久精品国产亚洲av品善| 午夜影视在线免费观看| 日韩亚洲产在线观看| 免费看国产精品3a黄的视频| 亚洲AV无码一区二区三区牛牛| 成人免费无码大片A毛片抽搐| 亚洲色大成网站www永久网站| 日韩精品免费电影| 国产精品亚洲二区在线| 亚洲av高清在线观看一区二区| 又粗又长又爽又长黄免费视频| 亚洲一区二区三区免费| 中国好声音第二季免费播放| 亚洲乱码日产一区三区| 国产精品视频白浆免费视频| 久久亚洲私人国产精品vA| 91精品成人免费国产片| 亚洲色欲色欲www| 免费无遮挡无码视频网站| 直接进入免费看黄的网站| AV在线亚洲男人的天堂| 免费人成在线观看视频高潮| 亚洲视频在线观看| 免费看成人AA片无码视频羞羞网| 亚洲中文字幕久久精品无码VA| 国产一区二区视频免费| gogo免费在线观看| 亚洲av无码av制服另类专区| 免费女人高潮流视频在线观看| 亚洲国产美女在线观看 | 99爱免费观看视频在线| 亚洲的天堂av无码| 免费无码成人AV片在线在线播放| 偷自拍亚洲视频在线观看99| 亚洲中文字幕久久精品无码喷水|