CPUID 指令的使用

使用 CPUID 指令可以从 processor 厂商里获得关于 processor 的详细信息,CPUID 指令是从 Intel 486 处理器以后开始加入支持。

1. 检测处理器是否支持 cpuid 指令

现在的处理器都支持 cpuid 指令,确实没必要去检测是否支持,除非在古老的机器上运行才有必要。

当然,这里只是作为一个知识点介绍,在 eflags.ID 标志位是 Processor Feature Identification 位,通过修改这个标志位的值,以此来检测是否支持 cpuid 指令。

;-------------------------------------------------------
; test cpuid enable
;-------------------------------------------------------
        pushfd                                            ; save eflags
        mov eax, dword [esp]                              ; get old eflags
        xor dword [esp], 0x200000                         ; xor the eflags.ID value
        popfd                                             ; restore new eflags
        pushfd                                            ; save eflags again
        pop ebx                                           ; get new eflags
        cmp eax, ebx                                      ; test eflags.ID is modify
        jne support                                       ; OK! support CPUID instruction


no_support:

        lea si, [failure_msg]
        mov ah, 0x0e
        xor bh, bh
        call printmsg

        jmp $


support:
        ... ...

上面这个代码能成功地修改 eflags.ID 标志位,说明 cpu 是支持 cpuid 指令的。

2. cpuid 的使用方法

cpuid 指令由 eax 寄存器获得输入,执行 cpuid 指令前,将功能号传给 eax 寄存器:

输入:

  • eax

输出:

  • eax
  • ebx
  • ecx
  • edx

所获得的 cpu 信息返回到 eaxebxecx 以及 edx 寄存器,每一个功能所得到的信息格式是不一样的。

mov eax, 0                   ; function 0
cpuid

上面代码中,将功能号 0 来获取信息,那么它将返回值是:

  • eax:最大的基本功能号
  • ebx:"Genu"
  • edx: "ineI"
  • ecx:"ntel"

这几个字符串组合起来就是 "GenuineIntel" 对于 AMD 的处理器来说,它返回的字符串是:"AuthenticAMD"

下面代码用来测试 CPU 的厂商是 intel 还是 amd

        mov eax, 0
        cpuid
        
test_intel:
        cmp ecx, 0x6c65746e
        jnz test_amd
        cmp edx, 0x49656e69
        jnz test_amd
        cmp ebx, 0x756e6547
        jnz test_amd
        lea si, [vendor_intel]
        call printmsg
        jz next_do

test_amd:
        cmp ecx, 0x444d4163        
        jnz test_other
        cmp edx, 0x69746e65
        jnz test_other
        cmp ebx, 0x68747541
        jnz test_other
        lea si, [vendor_amd]
        call printmsg
        jz next_do

test_other:
        lea si, [vendor_other]
        call printmsg

简单地通过直接比较 ebx, ecx 和 edx 的值来确定。

3. 获得最大功能号

cpuid 返回的信号包括:

  • 基本信息
  • 扩展信息

每种信息都有 CPU 所支持的最大功能号,扩展功能号以 0x80000000 开头

        mov eax, 0                          ; get largest basic function input
        cpuid

        mov eax, 0x80000000                 ; get largest extended function input
        cpuid

eax 寄存器返回的是 CPU 所支持的最大功能号,得到扩展最大功能号以 0x80000000 作为输入。

4. 得到 CPU 的基本功能信息

使用基本功能号 1 可以获得 CPU 的基本功能信息:

  • eax 返回 CPU 的家族型号等
  • ecx 和 edx 返回 CPU 的功能信息

        mov eax, 1
        cpuid
        mov esi, ecx
        mov ebx, ecx_feature_function_table
        call print_msg

 

;--------------------------------
; input:
;        esi: feature information
;        ebx: function table
;--------------------------------

print_msg:
        xor eax, eax

print_msg_loop:        
        cmp eax, 31
        jg print_msg_done
        
        lea edi, [ebx+eax*4]
        cmp dword [edi], 0
        jnz do_print_msg
        inc eax
        jmp print_msg_next
        
do_print_msg:
        mov edi, [edi]
        call puts
        
        bt esi, eax
        jc print_yes
        mov edi, no
        call puts
        jmp print_msg_next
        
print_yes:        
        mov edi, yes
        call puts

print_msg_next:        
        inc eax
        jmp print_msg_loop
        
print_msg_done:
        
        ret

 


yes                db 'yes', 10, 0
no                db 'no', 10, 0       

ecx_msg:
B0                db 'SSE3 Extension:                      ',  0
B1                db 'Carryless Multiplication:            ',  0
B2                db '64-bit DS Area:                      ',  0
B3                db 'MONITOR/MWAIT:                       ',  0
B4                db 'CPL Qualified Debug Store:           ',  0
B5                db 'Virtual Machine Extensions:          ',  0
B6                db 'SaferMode Extensions:                ',  0
B7                db 'Enhanced Intel SpeedStep Technology: ',  0
B8                db 'Thermal Monitor 2:                   ',  0
B9                db 'SSSE3 Extensions:                    ',  0
B10                db 'L1 Context ID:                       ',  0
B12                db 'Fused Multiply Add:                  ',  0
B13                db 'CMPXCHG16B:                          ',  0
B14                db 'Update Control:                      ',  0
B15                db 'Perf/Debug Capability MSR:           ',  0
B17                db 'Process-context Identifiers:         ',  0
B18                db 'Direct Cache Access:                 ',  0
B19                db 'SSE4.1:                              ',  0
B20                db 'SSE4.2:                              ',  0
B21                db 'x2APIC:                              ',  0
B22                db 'MOVEBE:                              ',  0
B23                db 'POPCNT:                              ',  0
B24                db 'TSC-Deadline:                        ',  0
B25                db 'AES:                                 ',  0
B26                db 'XSAVE:                               ',  0
B27                db 'OSXSAVE:                             ',  0
B28                db 'AVX:                                 ',  0


ecx_feature_function_table:
        dd B0
        dd B1
        dd B2
        dd B3
        dd B4
        dd B5
        dd B6
        dd B7
        dd B8
        dd B9
        dd B10
        dd 0                        ; reserved
        dd B12
        dd B13
        dd B14
        dd B15
        dd 0                        ; reserved
        dd B17
        dd B18
        dd B19
        dd B20
        dd B21
        dd B22
        dd B23
        dd B24
        dd B25
        dd B26
        dd B27
        dd B28
        dd 0                        ; reserved
        dd 0                        ; reserved
        dd 0                        ; 0

上面的代码读取 ecx,并显示出它的 feature 信息,下面是在 vmware 上的运行结果:

上面的信息是返回在 ecx 寄存器,返回在 edx 寄存器的信息是:

edx_msg:
BIT0        db 'FPU:  ', 0
BIT1        db 'VME:  ', 0
BIT2        db 'DE:   ', 0
BIT3        db 'PSE:  ', 0
BIT4        db 'TSC:  ', 0
BIT5        db 'MSR:  ', 0
BIT6        db 'PAE:  ', 0
BIT7        db 'MCE:  ', 0
BIT8        db 'CMPXCHG8B: ', 0
BIT9        db 'APIC: ', 0
BIT11        db 'SYSENTER/SYSEXIT:', 0
BIT12        db 'MTRR: ', 0
BIT13        db 'PGE:  ', 0
BIT14        db 'MCA:  ', 0
BIT15        db 'CMOV: ', 0
BIT16        db 'PAT:  ', 0
BIT17        db 'PSE36:', 0
BIT18        db 'PNS:  ', 0
BIT19        db 'CLFSH:', 0
BIT21        db 'Debug Store:', 0
BIT22        db 'ACPI: ', 0
BIT23        db 'MMX:  ', 0
BIT24        db 'FXSR: ', 0
BIT25        db 'SSE:  ', 0
BIT26         db 'SSE2: ', 0
BIT27        db 'Self snoop:', 0
BIT28        db 'HTT:  ', 0
BIT29        db 'TM:   ', 0
BIT31        db 'PBE:  ', 0


edx_feature_function_table:
        dd BIT0
        dd BIT1
        dd BIT2
        dd BIT3
        dd BIT4
        dd BIT5
        dd BIT6
        dd BIT7
        dd BIT8
        dd BIT9
        dd 0            ; reserved
        dd BIT11
        dd BIT12
        dd BIT13
        dd BIT14
        dd BIT15
        dd BIT16
        dd BIT17
        dd BIT18
        dd BIT19
        dd 0           ; reserved
        dd BIT21
        dd BIT22
        dd BIT23
        dd BIT24
        dd BIT25
        dd BIT26
        dd BIT27
        dd BIT28
        dd BIT29
        dd 0           ; reserved
        dd BIT31

运行结果如下:


示例代码:

http://download.csdn.net/detail/swanabin/6969253


posted @ 2014-02-27 14:49  vcerror  阅读(1579)  评论(0编辑  收藏  举报