下面的例子完全用VB进行ASM编程的示例,本例获得CPU ID
工程文件分为一个form1.frm 和一个模块module1.bas----------------------form1.frm的源文件---------------------VERSION 5.00
Begin VB.Form Form1 
  Caption        =  "Form1"
  ClientHeight    =  1965
  ClientLeft      =  60
  ClientTop      =  345
  ClientWidth    =  3105
  LinkTopic      =  "Form1"
  ScaleHeight    =  1965
  ScaleWidth      =  3105
  StartUpPosition =  2  'Bildschirmmitte
  Begin VB.CommandButton Command1 
      Caption        =  "Get CPU Name"
      Height          =  495
      Left            =  840
      TabIndex        =  0
      Top            =  315
      Width          =  1425
  End
  Begin VB.Label Label2 
      Alignment      =  2  'Zentriert
      AutoSize        =  -1  'True
      BeginProperty Font 
        Name            =  "MS Sans Serif"
        Size            =  9.75
        Charset        =  0
        Weight          =  400
        Underline      =  0  'False
        Italic          =  0  'False
        Strikethrough  =  0  'False
      EndProperty
      Height          =  240
      Left            =  1515
      TabIndex        =  2
      Top            =  1065
      Width          =  60
  End
  Begin VB.Label Label1 
      Alignment      =  2  'Zentriert
      AutoSize        =  -1  'True
      BeginProperty Font 
        Name            =  "Arial"
        Size            =  12
        Charset        =  0
        Weight          =  700
        Underline      =  0  'False
        Italic          =  0  'False
        Strikethrough  =  0  'False
      EndProperty
      Height          =  285
      Left            =  1515
      TabIndex        =  1
      Top            =  1350
      Width          =  75
  End
End
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Option ExplicitPrivate Sub Command1_MouseDown(Button As Integer, Shift As Integer, x As Single, Y As Single)    Label1 = ""
    Label2 = ""End SubPrivate Sub Command1_Click()
    
    Label1 = GetCpuName() & " CPU"
    Label2 = "You have a" & IIf(InStr("AEIOU", Left$(Label1, 1)), "n", "")End Sub
------------------------------end---------------------------------下面是modu1e.bas的源代码----------------------module1.bas的源文件--------------------------
Option Explicit
'
'This shows how to incorporate machine code into VB
'''''''''''''''''''''''''''''''''''''''''''''''''''
'The example fills the array with a few machine instructions and then copies
'them to a procedure address. The modified procedure is then called thru
'CallWindowProc. The result of this specific machine code is your CPU Vendor Name.
'
'##########################################################################
'Apparently it gets a Stack Pointer Error, but I don't know why; if anybody
'can fix that please let me know...                          [email protected]
'The Error is not present in the native compiled version; so I think it got
'something to do with the P-Code Calling Convention (strange though)...
'##########################################################################
'
'Sub Dummy serves to reserve some space to copy the machine instructions into.
'
'
'Tested on Intel and AMD CPU's (uncompiled and compiled)
'
'
Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (lpvDest As Any, lpvSource As Any, ByVal cbCopy As Long)
Private x As LongPublic Function GetCpuName() As String
  
  Dim MachineCode(0 To 35)  As Byte
  Dim VarAddr              As Long
  Dim FunctAddr            As Long
  Dim EAX                  As Long
  Dim CPUName(1 To 12)      As Byte
  
  'set up machine code
    
    MachineCode(0) = &H55    'push ebp
    
    MachineCode(1) = &H8B    'move ebp,esp
    MachineCode(2) = &HEC
    
    MachineCode(3) = &H57    'push edi
    
    MachineCode(4) = &H52    'push edx
    
    MachineCode(5) = &H51    'push ecx
    
    MachineCode(6) = &H53    'push ebx
    
    MachineCode(7) = &H8B    'move eax,dword ptr [ebp+8]
    MachineCode(8) = &H45
    MachineCode(9) = &H8
    
    MachineCode(10) = &HF    'cpuid
    MachineCode(11) = &HA2
    
    MachineCode(12) = &H8B  'mov edi,dword ptr [ebp+12]
    MachineCode(13) = &H7D
    MachineCode(14) = &HC
    
    MachineCode(15) = &H89  'move dword ptr [edi],ebx
    MachineCode(16) = &H1F
    
    MachineCode(17) = &H8B  'mov edi,dword ptr [ebp+16]
    MachineCode(18) = &H7D
    MachineCode(19) = &H10
    
    MachineCode(20) = &H89  'move dword ptr [edi],ecx
    MachineCode(21) = &HF
    
    MachineCode(22) = &H8B  'mov edi,dword ptr [ebp+20]
    MachineCode(23) = &H7D
    MachineCode(24) = &H14
    
    MachineCode(25) = &H89  'move dword ptr [edi],edx
    MachineCode(26) = &H17
    
    MachineCode(27) = &H58  'pop ebx    MachineCode(28) = &H59  'pop ecx    MachineCode(29) = &H5A  'pop edx    MachineCode(30) = &H55  'pop edi
    
    MachineCode(31) = &HC9  'leave    MachineCode(32) = &HC2  'ret 16    I tried everything from 0 to 24
    MachineCode(33) = &H10  '          but all produce the stack error
    MachineCode(34) = &H0
    
    'tell cpuid what we want
    EAX = 0
    
    'get address of Machine Code
    VarAddr = VarPtr(MachineCode(0))
    
    'get address of Sub Dummy
    FunctAddr = GetAddress(AddressOf Dummy)
    
    'copy the Machine Code to where it can be called
    CopyMemory ByVal FunctAddr, ByVal VarAddr, 35 '35 bytes machine code
    
    'call it
    On Error Resume Next 'apparently it gets a stack pointer error when in P-Code but i dont know why
      CallWindowProc FunctAddr, EAX, VarPtr(CPUName(1)), VarPtr(CPUName(9)), VarPtr(CPUName(5))
      'Debug.Print Err; Err.Description
      'MsgBox Err & Err.Description
    On Error GoTo 0
    
    GetCpuName = StrConv(CPUName(), vbUnicode) 'UnicodeName
    
End FunctionPrivate Function GetAddress(Address As Long) As Long    GetAddress = AddressEnd FunctionPrivate Sub Dummy()  'the code below just reserves some space to copy the machine code into
  'it is never executed    x = 0
    x = 1
    x = 2
    x = 3
    x = 4
    x = 5
    x = 6
    x = 7
    x = 8
    x = 9
    x = 10
    x = 0
    x = 1
    x = 2
    x = 3
    x = 4
    x = 5
    x = 6
    x = 7
    x = 8
    x = 9
    x = 10
  
End Sub 
以上为转载他人代码

解决方案 »

  1.   

    是呀!
    asm有没有办法/
      

  2.   

    CPUID - CPU Identification
    0F A2  CPUID  EAX ?Processor identification informationDescription
    Provides processor identification information in registers EAX, EBX, ECX, and EDX. This information identifies Intel as the vendor, gives the family, model, and stepping of processor, feature information, and cache information. An input value loaded into the EAX register determines what information is returned.Information Returned by CPUID InstructionInitial EAX Value Information Provided about the Processor0 EAX Maximum CPUID Input Value (2 for the Pentium ?Pro processor and 1 for
    the Pentium processor and the later versions of Intel486?processor that
    support the CPUID instruction).
    EBX "Genu"
    ECX "ntel"
    EDX "ineI"
    1 EAX Version Information (Type, Family, Model, and Stepping ID)
    EBX Reserved
    ECX Reserved
    EDX Feature Information
    2 EAX Cache and TLB Information
    EBX Cache and TLB Information
    ECX Cache and TLB Information
    EDX Cache and TLB InformationThe CPUID instruction can be executed at any privilege level to serialize instruction execution. Serializing instruction execution guarantees that any modifications to flags, registers, and memory for previous instructions are completed before the next instruction is fetched and executed (see "Serializing Instructions" in Chapter 7 of the Intel Architecture Software Developer's Manual, Volume 3).When the input value in register EAX is 0, the processor returns the highest value the CPUID instruction recognizes in the EAX register (see Table 3-4). A vendor identification string is returned in the EBX, EDX, and ECX registers. For Intel processors, the vendor identification string is "GenuineIntel" as follows:EBX ?756e6547h (* "Genu", with G in the low nibble of BL *)
    EDX ?49656e69h (* "ineI", with i in the low nibble of DL *)
    ECX ?6c65746eh (* "ntel", with n in the low nibble of CL *)When the input value is 1, the processor returns version information in the EAX register and feature information in the EDX register (see Figure 3-3).The version information consists of an Intel Architecture family identifier, a model identifier, a stepping ID, and a processor type. The model, family, and processor type for the first processor in the Intel Pentium Pro family is as follows:
    ?Model?001B
    ?Family?110B
    ?Processor Type?0BSee AP-485, Intel Processor Identification and the CPUID Instruction (Order Number 241618), the Intel Pentium ?Pro Processor Specification Update (Order Number 242689), and the Intel Pe n t i u m ?Processor Specification Update (Order Number 242480) for more information on identifying earlier Intel Architecture processors.The available processor types are given in Table 3-5. Intel releases information on stepping IDs as needed.Type  Encoding
    Original OEM Processor  00BIntel OverDrive ?Processor  01B
    Dual processor  *10B
    Intel reserved.  11BTable 3-6 shows the encoding of the feature flags in the EDX register. A feature flag set to 1 indicates the corresponding feature is supported. Software should identify Intel as the vendor to properly interpret the feature flags.BiT Feature  Description
    0  FPU桭loating-Point Unit Processor contains an FPU and executes the Intel 387
    on Chip instruction set.1 VME梀irtual-8086 Processor supports the following virtual-8086 mode
    Mode Enhancements enhancements:
    ?CR4.VME bit enables virtual-8086 mode extensions.
    ?CR4.PVI bit enables protected-mode virtual interrupts.
    ?Expansion of the TSS with the software indirection bitmap.
    ?EFLAGS.VIF bit (virtual interrupt flag).
    ?EFLAGS.VIP bit (virtual interrupt pending flag).
    2 DE桪ebugging Processor supports I/O breakpoints, including the CR4.DE bitExtensions for enabling debug extensions and optional trapping of access
    to the DR4 and DR5 registers.
    3 PSE桺age Size Processor supports 4-Mbyte pages, including the CR4.PSE bit
    Extensions for enabling page size extensions, the modified bit in page
    directory entries (PDEs), page directory entries, and page table
    entries (PTEs).
    4 TSC桾ime Stamp Processor supports the RDTSC (read time stamp counter)
    Counter instruction, including the CR4.TSD bit that, along with the CPL,controls whether the time stamp counter can be read.
    5 MSR桵odel Specific Processor supports the RDMSR (read model-specific register)
    Registers and WRMSR (write model-specific register) instructions.
    6 PAE桺hysical Address Processor supports physical addresses greater than 32 bits, the
    Extension extended page-table-entry format, an extra level in the page
    translation tables, and 2-MByte pages. The CR4.PAE bit enables
    this feature. The number of address bits is implementation specific.The Pentium ?Pro processor supports 36 bits of addressing when
    the PAE bit is set.
    7 MCE桵achine Check Processor supports the CR4.MCE bit, enabling machine check
    Exception exceptions. However, this feature does not define the model-specific
    implementations of machine-check error logging, reporting,
    or processor shutdowns. Machine-check exception handlers might
    have to check the processor version to do model-specific
    processing of the exception or check for the presence of thestandard machine-check feature.
    8 CX8桟MPXCHG8B Processor supports the CMPXCHG8B (compare and exchange 8
    Instruction bytes) instruction.
    9 APIC Processor contains an on-chip Advanced Programmable Interrupt
    Controller (APIC) and it has been enabled and is available for use.
    10,11 Reserved
    12 MTRR桵emory Type Processor supports machine-specific memory-type range registers
    Range Registers (MTRRs). The MTRRs contains bit fields that indicate theprocessor's MTRR capabilities, including which memory types the
    processor supports, the number of variable MTRRs the processor
    supports, and whether the processor supports fixed MTRRs.
    13 PGE桺TE Global Flag Processor supports the CR4.PGE flag enabling the global bit in
    both PTDEs and PTEs. These bits are used to indicate translation
    lookaside buffer (TLB) entries that are common to different tasks
    and need not be flushed when control register CR3 is written.14 MCA桵achine Check Processor supports the MCG_CAP (machine check global
    Architecture capability) MSR. The MCG_CAP register indicates how many
    banks of error reporting MSRs the processor supports.
    15 CMOV桟onditional Processor supports the CMOV cc instruction and, if the FPU feature
    Move and Compare flag (bit 0) is also set, supports the FCMOV cc and FCOMI
    Instructions instructions.
    16-22 Reserved
    23 MMX?Technology Processor supports the MMX instruction set. These instructionsoperate in parallel on multiple data elements (8 bytes, 4 words, or 2
    doublewords) packed into quadword registers or memory locations.
    24-31 ReservedWhen the input value is 2, the processor returns information about the processor's internal caches and TLBs in the EAX, EBX, ECX, and EDX registers. The encoding of these registers is as follows:
    ?The least-significant byte in register EAX (register AL) indicates the number of times the CPUID instruction must be executed with an input value of 2 to get a complete description of the processor's caches and TLBs. The Pentium ?Pro family of processors will return a 1.
    ?The most significant bit (bit 31) of each register indicates whether the register contains valid information (cleared to 0) or is reserved (set to 1).
    ?If a register contains valid information, the information is contained in 1 byte descriptors. Table 3-7 shows the encoding of these descriptors.Descriptor Value  Cache or TLB Description
    00H  Null descriptor
    01H  Instruction TLB: 4K-Byte Pages, 4-way set associative, 32 entries
    02H  Instruction TLB: 4M-Byte Pages, 4-way set associative, 4 entries
    03H  Data TLB: 4K-Byte Pages, 4-way set associative, 64 entries
    04H  Data TLB: 4M-Byte Pages, 4-way set associative, 8 entries
    06H  Instruction cache: 8K Bytes, 4-way set associative, 32 byte line size
    08H  Instruction cache: 16K Bytes, 4-way set associative, 32 byte line size0AH  Data cache: 8K Bytes, 2-way set associative, 32 byte line size
    0CH  Data cache: 16K Bytes, 2-way set associative, 32 byte line size
    41H  Unified cache: 128K Bytes, 4-way set associative, 32 byte line size
    42H  Unified cache: 256K Bytes, 4-way set associative, 32 byte line size
    43H  Unified cache: 512K Bytes, 4-way set associative, 32 byte line size
    44H  Unified cache: 1M Byte, 4-way set associative, 32 byte line sizeThe first member of the Pentium Pro processor family will return the following information about caches and TLBs when the CPUID instruction is executed with an input value of 2:EAX 03 02 01 01H
    EBX 0H
    ECX 0H
    EDX 06 04 0A 42HThese values are interpreted as follows:
    ?The least-significant byte (byte 0) of register EAX is set to 01H, indicating that the CPUID instruction needs to be executed only once with an input value of 2 to retrieve complete information about the processor's caches and TLBs.
    ?The most-significant bit of all four registers (EAX, EBX, ECX, and EDX) is set to 0, indicating that each register contains valid 1-byte descriptors.
    ?Bytes 1, 2, and 3 of register EAX indicate that the processor contains the following:?01H桝 32-entry instruction TLB (4-way set associative) for mapping 4-KByte pages.
    ?02H桝 4-entry instruction TLB (4-way set associative) for mapping 4-MByte pages.
    ?03H桝 64-entry data TLB (4-way set associative) for mapping 4-KByte pages.?The descriptors in registers EBX and ECX are valid, but contain null descriptors.
    ?Bytes 0, 1, 2, and 3 of register EDX indicate that the processor contains the following:?42H桝 256-KByte unified cache (the L2 cache), 4-way set associative,
    with a 32-byte cache line size.
    ?0AH桝n 8-KByte data cache (the L1 data cache), 2-way set associative, with a
    32-byte cache line size.
    ?04H桝n 8-entry data TLB (4-way set associative) for mapping 4M-byte pages.
    ?06H桝n 8-KByte instruction cache (the L1 instruction cache), 4-way set associative,
    with a 32-byte cache line size.
    Operands Bytes Clocks
                     2        14   NPFlags
    None.
    这是在程序员大本营(微软版)中的汇编资料中截取的cpuid指令的用法,上文的vb程序也是用的这个指令,有一符图没法贴,你可以自己去查。
    可以在自己的程序中用db 0f0h,0a2h插入cpuid指令。
    不过从上文看,cpuid指令好像没有能得到cpu唯一标识的功能,只能得到cpu的一些信息。
      

  3.   

    cpuid是可以得到cpu唯一标识的,我有详细资料
      

  4.   

    wenhaoy.........发一份给我可否多谢,[email protected]
      

  5.   

    wenhaoy(wenhaoy):
         cpu唯一标识的详细资料 给我一份吧.不胜感激!!!
          [email protected]
      

  6.   

    to U_U and yizhanliu:详细资料我已经给你们发了,这仅仅是cpuid指令读取PSN(processor serial number)部分,还有一个是cpuid指令所有功能的详细介绍(比较大),如果要得话给我来信。
      

  7.   

    to wenhaoy(wenhaoy):
    你好,你的资料可以给我一份吗?
    [email protected]
      

  8.   

    去Intel找开发文档,CPU Identification
      

  9.   

    cpuid指令可以,下面是TASM的带来的例子...
    不过好像可以利用“标专寄存器”来判断
    ;       cpuid.asm 
    ;
    ;       CPU detector program.
    ;
    ;       Copyright (c) 1993 by Borland International, Inc.
    ;
    ;       Build with the provided makefile: make -B
            TITLE CPUID
            JUMPS
            .model small
            .stack 100h
            .data
    saved_cpuid     dd      ?
    vendor_id       db      12 dup (?)
    cpu_type        db      ?
    themodel        db      ?
    stepping        db      ?
    id_flag         db      0
    intel_proc      db      0
    id_msg          db      "This system has a$"
    c8086           db      "n 8086/8088 microprocessor$"
    c286            db      "n Intel 286 microprocessor$"
    c386            db      "n Intel386 (TM) microprocessor$"
    c486            db      "n Intel486 (TM) DX microprocessor$"
    Pentium         db      " Pentium(TM) microprocessor", 13, 10, "$"
    intel           db      "This system contains a Genuine Intel Processor", 13, 10, "$"
    modelmsg        db      "Model:         $"
    steppingmsg     db      "Stepping:      $"
    familymsg       db      "Processor Family: $"
    period          db      ".",13,10,"$"
    dataCR          db      ?,13,10,"$"
    intel_id        db      "GenuineIntel".code
    .8086            ; This part of the program must run on an 8086
    start:  mov     ax,@data
            mov     ds, ax                  ;set segment register
            mov     es, ax                  ;set segment register
            and     sp, not 3               ;align stack to avoid AC fault
            call    get_cpuid
            call    print
            mov     ax,4c00h                ; terminate program
            int     21hget_cpuid        proc;       8086 CPU check
    ;       Bits 12-15 are always set on the 8086 processor
    ;
    check_8086:
            pushf                           ;save FLAGS
            pop     bx                      ;store FLAGS in BX
            mov     ax, 0fffh               ;clear bits 12-15
            and     ax, bx                  ;  in FLAGS
            push    ax                      ;store new FLAGS calue on stack
            popf                            ;replace current FLAGS value
            pushf                           ;set new flags
            pop     ax                      ;store new flags in AX
            and     ax, 0f000h              ;if bits 12-15 are set, then CPU
            cmp     ax, 0f000h              ;  is an 8086/8088
            mov     cpu_type, 0             ; save the CPU type
            je      end_get_cpuid
    ;
    ;       Intel 286 CPU check
    ;       Bits 12-15 are always clear on the Intel processor.
    ;
    check_80286:
    .286
            or      bx, 0f000h              ;try to set bits 12-15
            push    bx
            popf
            pushf
            pop     ax
            and     ax, 0f000h              ; if bits 12-15 are cleared,
                                            ;       CPU=Intel 286
            mov     cpu_type, 2             ; turn on Intel 286 Cpu flag
            jz      end_get_cpuid           ; if CPU is intel 286, check
                                            ; for Intel 287 math coprocessor;       Intel386 CPU check
    ;       The AC bit (bit 18), is a new bit introduced in the EFLAGS
    ;       register on the Intel486 DX CPU to generate alignment faults.
    ;       This bit can not be set on the Intel386 CPU.
    ;
    check_intel386:
    .386
            pushfd
            pop     eax                     ;get original EFLAGS
            mov     ecx,eax                 ; save original EFLAGS
            xor     eax,40000h              ;flip AC bit in EFLAGS
            push    eax                     ; save for EFLAGS
            popfd                           ; copy to EFLAGS
            pushfd                          ; push EFLAGS
            pop     eax                     ; get new EFLAGS value
            xor     eax,ecx                 ; can't toggle AC bit, CPU=Intel386
            mov     cpu_type, 3             ; turn on Intel386 CPU flag
            je      end_get_cpuid           ; if CPU is Intel386, now check
                                            ; for an Intel 287 or Intel387 MCP;     Intel486 DX CPU, Intel 487 SX MCP, and Intel486 SX CPU checking
    ;
    ;     Checking for the ability to set/clear the ID flag (bit 21) in EFLAGS
    ;     which diferentiates between Pentium (or greater) and the Intel486.
    ;     If the ID flag is set then the CPUID instruction can be used to
    ;     determine the final version of the chip, else it's a 486
    ;
    ;
    check_Intel486:
    .486
            mov     cpu_type, 4             ;turn on Intel486 CPU flag
            pushfd                          ;push original EFLAGS
            pop     eax                     ; get original EFLAGS in eax
            mov     ecx,eax                 ;save original EFLAGS in ecx
            or      eax,200000h             ; flip ID bit in EFLAGS
            push    eax                     ;save for EFLAGS
            popfd                           ;copy to EFLAGS
            pushfd                          ;push EFLAGS
            pop     eax                     ;get new EFLAGS value
            xor     eax,ecx
            je      end_get_cpuid           ;if ID bit cannot be changed,
                                            ;CPU=Intel486 without CPUID
                                            ;instruction functionality;       Otherwise, execute CPUID instruction to determine vendor,
    ;       family, model and stepping.check_vendor:
    .586
            mov     id_flag, 1              ; set flag for indicating use of
                                            ;CPUID inst
            mov     eax, 0                  ;set up for CPUID instruction
            cpuid
            mov     dword ptr vendor_id, ebx; Test for "GenuineIntel" vendor id.
            mov     dword ptr  vendor_id[+4], edx
            mov     dword ptr vendor_id[+8], ecx
            mov     si, offset vendor_id
            mov     di, offset intel_id
            mov     cx, length intel_id
    compare:
            repe    cmpsb
            cmp     cx, 0                   ; must be a GenuineIntel if ecx =0
            jne     cpuid_dataintel_processor:
            mov     intel_proc, 1
            mov     [intel-1], ' '          ; add a space so the Genuine Intel 
                                            ; message prints out.cpuid_data:
            mov     eax, 1
            cpuid
            mov     saved_cpuid,eax         ;save for future use
            and     eax, 0F00H              ; mask everything but family
            shr     eax, 8
            mov     cpu_type, al            ; set cpu_type with family        mov     eax,saved_cpuid         ;restore data
            mov     stepping, al
            and     stepping, 0FH           ; isolate stepping info        mov     eax, saved_cpuid
            mov     themodel, al
            and     themodel, 0F0H          ; isolate model info
            shr     themodel, 4end_get_cpuid:
    .8086
            ret
    get_cpuid       endp;
    ;       This procedure prints the appropriate cpuid string
    ;       If the CPUID instruction was supported, it prints out
    ;       the cpuid info.print   proc
            push    ax
            push    bx
            push    cx
            push    dx
            cmp     id_flag, 1              ; if set to 1, cpu supported CPUID
                                            ; instruction
                                            ; print detailed CPUID information
            je      print_cpuid_data        mov     dx, offset id_msg 
            mov     ah, 9h
            int     21h                     ; print initial messageprint_86:
            cmp     cpu_type, 0
            jne     print_286
            mov     dx, offset c8086
            mov     ah, 9h
            int     21h
            jmp     end_printprint_286:
            cmp     cpu_type, 2
            jne     print_386
            mov     dx, offset c286
            mov     ah, 9h
            int     21h
            jmp     end_print
    print_386:
            cmp     cpu_type, 3
            jne     print_486
            mov     dx, offset c386
            mov     ah, 9h
            int     21h
            jmp     end_print
    print_486:
            mov     dx, offset  c486
            mov     ah, 9h
            int     21h
            jmp     end_printprint_cpuid_data:        cmp     cpu_type, 5
            jne     print_cpuid_cont        mov     dx, offset Pentium
            mov     ah, 9
            int     21hprint_cpuid_cont:
            mov     dx, offset familymsg    ;print family msg
            mov     ah, 9h
            int     21h
            mov     al, cpu_type
            mov     byte ptr dataCR, al
            add     byte ptr dataCR, 30H    ; convert to ASCII
            mov     dx,  offset dataCR      ; print family info
            mov     ah, 9h
            int     21h        mov     dx, offset steppingmsg  ; print stepping msg
            mov     ah, 9h
            int     21h
            mov     al, stepping
            mov     byte ptr dataCR, al
            add     byte ptr dataCR, 30H    ; convert to ASCII
            mov     dx, offset dataCR       ; print stepping info
            mov     ah, 9h
            int     21h        mov     dx, offset modelmsg     ; print model msg
            mov     ah, 9h
            int     21h
            mov     al, themodel
            mov     byte ptr dataCR, al
            add     byte ptr dataCR, 30H    ; convert to ASCII
            mov     dx, offset dataCR       ; print stepping info
            mov     ah, 9h
            int     21h
    end_print:
            pop     dx
            pop     cx
            pop     bx
            pop     ax
            ret
    print   endp        end     start