HelloWorld 善戰(zhàn)者,求之于勢,不責(zé)于人;故能擇人而任勢。

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

            BlogJava :: 首頁 ::  :: 聯(lián)系 ::  :: 管理 ::
            167 隨筆 :: 1 文章 :: 40 評(píng)論 :: 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位,如果程序可以清楚/設(shè)置它,則說明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) ) )
                        );

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

              /* 把原來的eflags值設(shè)置回去 */
              asm volatile ("pushl %0\n\t"
                        "popf"
                        :
                        : "g"(eflags1)
                        );
              /**
               * FIXME: Intel文檔并沒有說,如果不支持CPUID的話,clear/set eflags的第21位會(huì)有什么錯(cuò)誤。
               * 它只說,在不支持CPUID指令的CPU上,如80386,執(zhí)行CPUID會(huì)產(chǎn)生invalid opcode錯(cuò)誤
               *
               * 所以,在這里我們不處理 讀/寫 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是個(gè)不可見字符,會(huì)把它前一個(gè)吃掉

                  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
               * 序列號(hào)有96位,其中最高32位即是eax的輸出值。應(yīng)當(dāng)把它保存下來,然后
               * 再設(shè)置eax==3, 取剩下的64位
               */
              asm volatile ("cpuid"
                        : "=a"(eax), "=d"(edx)
                        : "a"(1)
                        );
              if ( edx & (1 << 18) ) {
                  /* serial number supported */
                  /* edx輸出中間32位的序列號(hào),ecx輸出最低32位的序列號(hào) */
                  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上實(shí)現(xiàn)的core CPUs數(shù)目
               */
              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 閱讀(2388) 評(píng)論(0)  編輯  收藏 所屬分類: Linux/C
          主站蜘蛛池模板: 遵义市| 大姚县| 乌兰浩特市| 麻江县| 大同市| 临安市| 崇礼县| 清流县| 项城市| 苏尼特右旗| 安义县| 鄂州市| 黑山县| 保定市| 福泉市| 东阳市| 石林| 丽水市| 呼和浩特市| 福贡县| 梅河口市| 同仁县| 宿迁市| 罗定市| 乌拉特后旗| 百色市| 玛多县| 大宁县| 益阳市| 绵竹市| 云阳县| 千阳县| 海南省| 北碚区| 休宁县| 紫云| 榆中县| 安徽省| 博乐市| 中超| 南丹县|