コンテンツにスキップ

AMD64アセンブラ/AMD64 CPU情報表示ツール

出典: フリー教科書『ウィキブックス(Wikibooks)』

AMD64/x86_64アーキテクチャ向けのCPUID情報表示ツールを作成しました。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <cpuid.h>

// CPUID命令を実行する関数
static inline void cpuid(unsigned int leaf, unsigned int subleaf,
                         unsigned int *eax, unsigned int *ebx,
                         unsigned int *ecx, unsigned int *edx) {
    __cpuid_count(leaf, subleaf, *eax, *ebx, *ecx, *edx);
}

// ベンダー文字列の取得
void get_vendor_string(char *vendor) {
    unsigned int eax, ebx, ecx, edx;
    cpuid(0, 0, &eax, &ebx, &ecx, &edx);
    
    memcpy(vendor, &ebx, 4);
    memcpy(vendor + 4, &edx, 4);
    memcpy(vendor + 8, &ecx, 4);
    vendor[12] = '\0';
}

// プロセッサブランド文字列の取得
void get_brand_string(char *brand) {
    unsigned int eax, ebx, ecx, edx;
    
    for (int i = 0; i < 3; i++) {
        cpuid(0x80000002 + i, 0, &eax, &ebx, &ecx, &edx);
        memcpy(brand + (i * 16), &eax, 4);
        memcpy(brand + (i * 16) + 4, &ebx, 4);
        memcpy(brand + (i * 16) + 8, &ecx, 4);
        memcpy(brand + (i * 16) + 12, &edx, 4);
    }
    brand[48] = '\0';
}

// 基本CPU情報のデコード
void decode_cpu_signature() {
    unsigned int eax, ebx, ecx, edx;
    cpuid(1, 0, &eax, &ebx, &ecx, &edx);
    
    unsigned int stepping = eax & 0xF;
    unsigned int model = (eax >> 4) & 0xF;
    unsigned int family = (eax >> 8) & 0xF;
    unsigned int processor_type = (eax >> 12) & 0x3;
    unsigned int extended_model = (eax >> 16) & 0xF;
    unsigned int extended_family = (eax >> 20) & 0xFF;
    
    // 実際のファミリーとモデルの計算
    unsigned int display_family = family;
    unsigned int display_model = model;
    
    if (family == 0xF) {
        display_family = family + extended_family;
    }
    if (family == 0x6 || family == 0xF) {
        display_model = (extended_model << 4) + model;
    }
    
    printf("=== CPU Signature (CPUID.01H:EAX) ===\n");
    printf("Raw value: 0x%08x\n", eax);
    printf("Stepping: %u\n", stepping);
    printf("Model: 0x%x (%u)\n", display_model, display_model);
    printf("Family: 0x%x (%u)\n", display_family, display_family);
    printf("Processor Type: %u ", processor_type);
    switch(processor_type) {
        case 0: printf("(Original OEM Processor)\n"); break;
        case 1: printf("(Intel OverDrive Processor)\n"); break;
        case 2: printf("(Dual Processor)\n"); break;
        case 3: printf("(Reserved)\n"); break;
    }
    
    printf("Brand Index: %u\n", ebx & 0xFF);
    printf("CLFLUSH line size: %u bytes\n", ((ebx >> 8) & 0xFF) * 8);
    printf("Max Addressable IDs: %u\n", (ebx >> 16) & 0xFF);
    printf("Initial APIC ID: %u\n", (ebx >> 24) & 0xFF);
    printf("\n");
}

// キャッシュ情報の取得と表示
void decode_cache_info() {
    unsigned int eax, ebx, ecx, edx;
    
    printf("=== Cache and TLB Information ===\n");
    
    // Intel方式: CPUID.04H
    cpuid(0, 0, &eax, &ebx, &ecx, &edx);
    if (eax >= 4) {
        int cache_level = 0;
        while (1) {
            cpuid(4, cache_level, &eax, &ebx, &ecx, &edx);
            
            unsigned int cache_type = eax & 0x1F;
            if (cache_type == 0) break;
            
            unsigned int level = (eax >> 5) & 0x7;
            unsigned int ways = ((ebx >> 22) & 0x3FF) + 1;
            unsigned int partitions = ((ebx >> 12) & 0x3FF) + 1;
            unsigned int line_size = (ebx & 0xFFF) + 1;
            unsigned int sets = ecx + 1;
            unsigned int size = ways * partitions * line_size * sets;
            
            printf("L%u ", level);
            switch(cache_type) {
                case 1: printf("Data Cache: "); break;
                case 2: printf("Instruction Cache: "); break;
                case 3: printf("Unified Cache: "); break;
            }
            printf("%u KB, %u-way, %u byte line size\n",
                   size / 1024, ways, line_size);
            
            cache_level++;
        }
    }
    
    // AMD方式: CPUID.8000001DH
    cpuid(0x80000000, 0, &eax, &ebx, &ecx, &edx);
    if (eax >= 0x80000006) {
        cpuid(0x80000006, 0, &eax, &ebx, &ecx, &edx);
        
        unsigned int l2_line = ecx & 0xFF;
        unsigned int l2_assoc = (ecx >> 12) & 0xF;
        unsigned int l2_size = (ecx >> 16) & 0xFFFF;
        
        printf("L2 Cache: %u KB, line size %u bytes\n", l2_size, l2_line);
        
        unsigned int l3_line = edx & 0xFF;
        unsigned int l3_assoc = (edx >> 12) & 0xF;
        unsigned int l3_size = ((edx >> 18) & 0x3FFF) * 512;
        
        if (l3_size > 0) {
            printf("L3 Cache: %u KB, line size %u bytes\n",
                   l3_size / 1024, l3_line);
        }
    }
    printf("\n");
}

// 機能フラグの確認
void check_feature_flags() {
    unsigned int eax, ebx, ecx, edx;
    
    printf("=== Feature Flags (CPUID.01H) ===\n");
    cpuid(1, 0, &eax, &ebx, &ecx, &edx);
    
    printf("ECX Features:\n");
    if (ecx & (1 << 0)) printf("  - SSE3\n");
    if (ecx & (1 << 1)) printf("  - PCLMULQDQ\n");
    if (ecx & (1 << 3)) printf("  - MONITOR/MWAIT\n");
    if (ecx & (1 << 5)) printf("  - VMX (Virtual Machine Extensions)\n");
    if (ecx & (1 << 6)) printf("  - SMX (Safer Mode Extensions)\n");
    if (ecx & (1 << 9)) printf("  - SSSE3\n");
    if (ecx & (1 << 12)) printf("  - FMA\n");
    if (ecx & (1 << 13)) printf("  - CMPXCHG16B\n");
    if (ecx & (1 << 19)) printf("  - SSE4.1\n");
    if (ecx & (1 << 20)) printf("  - SSE4.2\n");
    if (ecx & (1 << 22)) printf("  - MOVBE\n");
    if (ecx & (1 << 23)) printf("  - POPCNT\n");
    if (ecx & (1 << 25)) printf("  - AES\n");
    if (ecx & (1 << 26)) printf("  - XSAVE\n");
    if (ecx & (1 << 28)) printf("  - AVX\n");
    if (ecx & (1 << 29)) printf("  - F16C\n");
    if (ecx & (1 << 30)) printf("  - RDRAND\n");
    
    printf("\nEDX Features:\n");
    if (edx & (1 << 0)) printf("  - FPU (x87 FPU)\n");
    if (edx & (1 << 4)) printf("  - TSC (Time Stamp Counter)\n");
    if (edx & (1 << 5)) printf("  - MSR (Model Specific Registers)\n");
    if (edx & (1 << 6)) printf("  - PAE (Physical Address Extension)\n");
    if (edx & (1 << 8)) printf("  - CX8 (CMPXCHG8B)\n");
    if (edx & (1 << 9)) printf("  - APIC\n");
    if (edx & (1 << 11)) printf("  - SEP (SYSENTER/SYSEXIT)\n");
    if (edx & (1 << 13)) printf("  - PGE (Page Global Enable)\n");
    if (edx & (1 << 15)) printf("  - CMOV\n");
    if (edx & (1 << 19)) printf("  - CLFSH (CLFLUSH)\n");
    if (edx & (1 << 23)) printf("  - MMX\n");
    if (edx & (1 << 24)) printf("  - FXSR (FXSAVE/FXRSTOR)\n");
    if (edx & (1 << 25)) printf("  - SSE\n");
    if (edx & (1 << 26)) printf("  - SSE2\n");
    if (edx & (1 << 28)) printf("  - HTT (Hyper-Threading)\n");
    
    // 拡張機能フラグ
    cpuid(0x80000000, 0, &eax, &ebx, &ecx, &edx);
    if (eax >= 0x80000001) {
        cpuid(0x80000001, 0, &eax, &ebx, &ecx, &edx);
        
        printf("\nExtended ECX Features:\n");
        if (ecx & (1 << 0)) printf("  - LAHF/SAHF in 64-bit mode\n");
        if (ecx & (1 << 5)) printf("  - ABM (Advanced Bit Manipulation)\n");
        if (ecx & (1 << 6)) printf("  - SSE4A\n");
        if (ecx & (1 << 8)) printf("  - PREFETCHW\n");
        if (ecx & (1 << 11)) printf("  - XOP\n");
        if (ecx & (1 << 16)) printf("  - FMA4\n");
        if (ecx & (1 << 21)) printf("  - TBM (Trailing Bit Manipulation)\n");
        
        printf("\nExtended EDX Features:\n");
        if (edx & (1 << 11)) printf("  - SYSCALL/SYSRET\n");
        if (edx & (1 << 20)) printf("  - NX (Execute Disable Bit)\n");
        if (edx & (1 << 22)) printf("  - MMXEXT\n");
        if (edx & (1 << 26)) printf("  - 1GB Pages\n");
        if (edx & (1 << 27)) printf("  - RDTSCP\n");
        if (edx & (1 << 29)) printf("  - Long Mode (64-bit)\n");
        if (edx & (1 << 30)) printf("  - 3DNow!+\n");
        if (edx & (1 << 31)) printf("  - 3DNow!\n");
    }
    
    // AVX2などの追加機能
    cpuid(0, 0, &eax, &ebx, &ecx, &edx);
    if (eax >= 7) {
        cpuid(7, 0, &eax, &ebx, &ecx, &edx);
        
        printf("\nStructured Extended Features (Leaf 7):\n");
        if (ebx & (1 << 3)) printf("  - BMI1\n");
        if (ebx & (1 << 5)) printf("  - AVX2\n");
        if (ebx & (1 << 8)) printf("  - BMI2\n");
        if (ebx & (1 << 16)) printf("  - AVX512F\n");
        if (ebx & (1 << 18)) printf("  - RDSEED\n");
        if (ebx & (1 << 19)) printf("  - ADX\n");
        if (ebx & (1 << 29)) printf("  - SHA\n");
    }
    printf("\n");
}

// /proc/cpuinfoから情報を読み取る
void read_proc_cpuinfo() {
    FILE *fp = fopen("/proc/cpuinfo", "r");
    if (!fp) {
        perror("Failed to open /proc/cpuinfo");
        return;
    }
    
    printf("=== /proc/cpuinfo Information ===\n");
    char line[256];
    int cpu_count = 0;
    
    while (fgets(line, sizeof(line), fp)) {
        if (strncmp(line, "processor", 9) == 0) {
            cpu_count++;
        } else if (strncmp(line, "model name", 10) == 0 ||
                   strncmp(line, "cpu family", 10) == 0 ||
                   strncmp(line, "model", 5) == 0 ||
                   strncmp(line, "stepping", 8) == 0 ||
                   strncmp(line, "cpu MHz", 7) == 0 ||
                   strncmp(line, "cache size", 10) == 0 ||
                   strncmp(line, "physical id", 11) == 0 ||
                   strncmp(line, "siblings", 8) == 0 ||
                   strncmp(line, "core id", 7) == 0 ||
                   strncmp(line, "cpu cores", 9) == 0) {
            if (cpu_count <= 1) {  // 最初のCPUの情報のみ表示
                printf("%s", line);
            }
        }
    }
    
    printf("Total logical processors: %d\n\n", cpu_count);
    fclose(fp);
}

// トポロジー情報の取得
void decode_topology() {
    unsigned int eax, ebx, ecx, edx;
    
    printf("=== CPU Topology ===\n");
    
    cpuid(1, 0, &eax, &ebx, &ecx, &edx);
    unsigned int max_logical = (ebx >> 16) & 0xFF;
    printf("Maximum addressable logical processors: %u\n", max_logical);
    
    cpuid(0, 0, &eax, &ebx, &ecx, &edx);
    if (eax >= 0xB) {
        int level = 0;
        while (1) {
            cpuid(0xB, level, &eax, &ebx, &ecx, &edx);
            
            unsigned int level_type = (ecx >> 8) & 0xFF;
            if (level_type == 0) break;
            
            unsigned int shift = eax & 0x1F;
            unsigned int num_logical = ebx & 0xFFFF;
            
            printf("Level %d: ", level);
            switch(level_type) {
                case 1: printf("SMT (threads per core)"); break;
                case 2: printf("Core"); break;
                default: printf("Unknown"); break;
            }
            printf(" - %u logical processors, shift %u\n", num_logical, shift);
            
            level++;
        }
    }
    printf("\n");
}

int main() {
    printf("AMD64/x86_64 CPU Information Display\n");
    printf("=====================================\n\n");
    
    // ベンダー文字列の取得
    char vendor[13];
    get_vendor_string(vendor);
    printf("=== Vendor Information ===\n");
    printf("Vendor ID: %s\n", vendor);
    
    // 対応している最大CPUIDリーフの確認
    unsigned int max_leaf, ebx, ecx, edx;
    cpuid(0, 0, &max_leaf, &ebx, &ecx, &edx);
    printf("Maximum standard CPUID leaf: 0x%x\n", max_leaf);
    
    cpuid(0x80000000, 0, &max_leaf, &ebx, &ecx, &edx);
    printf("Maximum extended CPUID leaf: 0x%x\n", max_leaf);
    
    // ブランド文字列の取得
    if (max_leaf >= 0x80000004) {
        char brand[49];
        get_brand_string(brand);
        printf("Processor Brand: %s\n", brand);
    }
    printf("\n");
    
    // CPU署名のデコード
    decode_cpu_signature();
    
    // キャッシュ情報の表示
    decode_cache_info();
    
    // トポロジー情報
    decode_topology();
    
    // 機能フラグの確認
    check_feature_flags();
    
    // /proc/cpuinfoから情報を読み取り
    read_proc_cpuinfo();
    
    // 基本的なシステム情報
    printf("=== System Information ===\n");
    printf("Page size: %ld bytes\n", sysconf(_SC_PAGESIZE));
    printf("Number of processors online: %ld\n", sysconf(_SC_NPROCESSORS_ONLN));
    printf("Number of processors configured: %ld\n", sysconf(_SC_NPROCESSORS_CONF));
    
    return 0;
}
実行例
AMD64/x86_64 CPU Information Display
=====================================

=== Vendor Information ===
Vendor ID: GenuineIntel
Maximum standard CPUID leaf: 0x1f
Maximum extended CPUID leaf: 0x80000008
Processor Brand: Intel(R) N100

=== CPU Signature (CPUID.01H:EAX) ===
Raw value: 0x000b06e0
Stepping: 0
Model: 0xbe (190)
Family: 0x6 (6)
Processor Type: 0 (Original OEM Processor)
Brand Index: 0
CLFLUSH line size: 64 bytes
Max Addressable IDs: 4
Initial APIC ID: 2

=== Cache and TLB Information ===
L1 Data Cache: 32 KB, 8-way, 64 byte line size
L1 Instruction Cache: 64 KB, 8-way, 64 byte line size
L2 Unified Cache: 2048 KB, 16-way, 64 byte line size
L3 Unified Cache: 6144 KB, 12-way, 64 byte line size
L2 Cache: 2048 KB, line size 64 bytes

=== CPU Topology ===
Maximum addressable logical processors: 4
Level 0: SMT (threads per core) - 1 logical processors, shift 0

=== Feature Flags (CPUID.01H) ===
ECX Features:
  - SSE3
  - PCLMULQDQ
  - VMX (Virtual Machine Extensions)
  - SSSE3
  - FMA
  - CMPXCHG16B
  - SSE4.1
  - SSE4.2
  - MOVBE
  - POPCNT
  - AES
  - XSAVE
  - AVX
  - F16C
  - RDRAND

EDX Features:
  - FPU (x87 FPU)
  - TSC (Time Stamp Counter)
  - MSR (Model Specific Registers)
  - PAE (Physical Address Extension)
  - CX8 (CMPXCHG8B)
  - APIC
  - SEP (SYSENTER/SYSEXIT)
  - PGE (Page Global Enable)
  - CMOV
  - CLFSH (CLFLUSH)
  - MMX
  - FXSR (FXSAVE/FXRSTOR)
  - SSE
  - SSE2
  - HTT (Hyper-Threading)

Extended ECX Features:
  - LAHF/SAHF in 64-bit mode
  - ABM (Advanced Bit Manipulation)
  - PREFETCHW

Extended EDX Features:
  - SYSCALL/SYSRET
  - NX (Execute Disable Bit)
  - 1GB Pages
  - RDTSCP
  - Long Mode (64-bit)

Structured Extended Features (Leaf 7):
  - BMI1
  - AVX2
  - BMI2
  - RDSEED
  - ADX
  - SHA

=== /proc/cpuinfo Information ===
cpu family      : 6
model           : 190
model name      : Intel(R) N100
stepping        : 0
cpu MHz         : 806.400
cache size      : 6144 KB
physical id     : 0
siblings        : 1
core id         : 0
cpu cores       : 1
Total logical processors: 4

=== System Information ===
Page size: 4096 bytes
Number of processors online: 4
Number of processors configured: 4

AMD64/x86_64版のCPU情報表示ツールを作成しました。主な特徴は以下の通りです:

主な機能

[編集]
  1. CPUID命令によるCPU情報取得
    • ベンダーID(Intel、AMD等)
    • プロセッサブランド文字列
    • ファミリー、モデル、ステッピング情報
  2. キャッシュ階層の詳細情報
    • L1/L2/L3キャッシュのサイズと構成
    • キャッシュラインサイズ
    • ウェイ数
  3. 豊富な機能フラグ検出
    • SSE/SSE2/SSE3/SSSE3/SSE4.1/SSE4.2
    • AVX/AVX2/AVX512
    • AES-NI、SHA拡張命令
    • 仮想化支援機能(VMX)
    • 64ビットモード対応確認
  4. CPUトポロジー情報
    • 論理プロセッサ数
    • SMT/ハイパースレッディング情報
    • コア数の取得
  5. /proc/cpuinfoとの連携
    • カーネルから見たCPU情報との照合

コンパイルと実行

[編集]
clang -o cpuinfo_amd64 cpuinfo_amd64.c
./cpuinfo_amd64

ARM64版と同様に、システムの深い部分から直接ハードウェア情報を取得し、詳細な分析を提供します。