The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: marco1974 on March 08, 2005, 06:17:04 AM

Title: Bit format, cpuid bits hmm whats the diff 0-7 bit and how do i access it?
Post by: marco1974 on March 08, 2005, 06:17:04 AM
Hello friends,

Have any of u read the Intel manuals?
They are well documented  ;-)

I am having the folowing problem:
The manual states for example that u can request BIT 23!
like here:

Quote

mov eax,1 ;requist feature flags
cpuid     ;0fh 0dh = cpuid instructrion
test edx,00800000h ; is bit 23 of edx set?
jnz mmx_found
mov eax,0

mmx_found:
etc,etc


If i think this one over i came stuck!
What if i want to access bit 2 or 3. I am stuck in a way that i can`t understand how they
come TO bit23.

WHATS THE MAGIC OF SETTING THOSE BITS?
I mean they talk about bit x,y,z and set for example a value of 080000h in edx.

That confuses me a whole lot. Thats the reason i can`t understand the INTEL MANUALS.

Can somebody explain it to me?

Thanx.








Title: Re: Bit format, cpuid bits hmm whats the diff 0-7 bit and how do i access it?
Post by: Petroizki on March 08, 2005, 06:24:01 AM
First of all, see this page about the cpuid instruction: http://www.sandpile.org/ia32/cpuid.htm.

When using cpuid instruction, with eax = 1, you will get eax, ebx, ecx and edx registers filled with some processor specific information. The bit 23 in edx, after the cpuid instruction tells you if the processor supports MMX.

test instruction is the same as and, but it won't save the result anywhere, only modifies flags. So it's very basic bit testing.
Title: Re: Bit format, cpuid bits hmm whats the diff 0-7 bit and how do i access it?
Post by: donkey on March 08, 2005, 06:25:04 AM
The MMX bit is bit 23,I usually just use BT to test the bit...

bt edx, 23
jc >.MMXPRESENT
; No MMX

You can use my IsFeaturePresent function found in the system.lib file on my website, or just use the source directly, it tests for various processor features and is "safe" in that it verifies that the CPUID function is available before attempting to execute it. It will also test for certain AMD features... (GoAsm syntax)

IsFeaturePresent
Checks the CPU for the availability of specific instructions
or features.

Parameters:
fFeature = A set of OR'ed flags indicating the features to verify:

IFP_MMX equ 1 ; MMX technology
IFP_SSE equ 2 ; SSE
IFP_SSE2 equ 4 ; SSE2
IFP_SSE3 equ 8 ; SSE3
IFP_AMD3D equ 16 ; AMD 3DNow!
IFP_AMD3D2 equ 32 ; AMD 3DNow! 2

IFP_APIC equ 65536 ; APIC timer present
IFP_CMOV equ 131072 ; CMOV instruction available
IFP_HTT equ 262144 ; Hyperthreading processor
IFP_TSC equ 524288 ; Timestamp clock available (RDTSC)

Returns 1 if all requested features are available, 0 otherwise

Tested GoAsm & MASM


IFP_MMX equ 1
IFP_SSE equ 2
IFP_SSE2 equ 4
IFP_SSE3 equ 8
IFP_AMD3D equ 16
IFP_AMD3D2 equ 32

IFP_APIC equ 65536
IFP_CMOV equ 131072
IFP_HTT equ 262144
IFP_TSC equ 524288

CODE SECTION

IsFeaturePresent FRAME fFeature
uses esi,edi,ebx


; This will test to see if CPUID is available on the system
pushfd
pop eax
mov ecx,eax
xor eax,000200000h
push eax
popfd
pushfd
pop eax
cmp eax,ecx
jnz >
xor eax,eax
ret
:


; CPUID is avialable, only 486SX and below do not have it anyway
xor eax,eax
inc eax
cpuid

; EDX contains feature info
mov edi,[fFeature]

test edi, IFP_MMX
jz >
bt edx,23
jc >
xor eax,eax
ret
:

test edi, IFP_SSE
jz >
bt edx,25
jc >
xor eax,eax
ret
:

test edi, IFP_SSE2
jz >
bt edx,26
jc >
xor eax,eax
ret
:

test edi, IFP_SSE3
jz >
bt ecx,0
jc >
xor eax,eax
ret
:

test edi, IFP_CMOV
jz >
bt edx,15
jc >
xor eax,eax
ret
:

test edi, IFP_APIC
jz >
bt edx,9
jc >
xor eax,eax
ret
:

test edi, IFP_HTT
jz >
bt edx,28
jc >
xor eax,eax
ret
:

test edi, IFP_TSC
jz >
xor esi,esi
bt edx,4
jc >
xor eax,eax
ret
:

/*
; Check to make sure this is not an Intel processor
and eax,0ff00h
and eax,0B00h
cmp eax,0B00h
je >.EXIT
*/

; AMD Specific
push edi ; These are not supposed to be affected but just in case...
mov eax,80000001h
CPUID
pop edi

test edi, IFP_AMD3D
jz >
bt edx,31
jc >
xor eax,eax
ret
:

test edi, IFP_AMD3D2
jz >
bt edx,30
jc >
xor eax,eax
ret
:

.EXIT
xor eax,eax
inc eax
RET
ENDF
Title: Re: Bit format, cpuid bits hmm whats the diff 0-7 bit and how do i access it?
Post by: marco1974 on March 08, 2005, 07:00:28 AM
wow the reply time is verry fast.

Thanx for the sample code.

But it was an example.  I meant that if i dont understand the bit TOPICS of the intel manuals.


The intel manual has various topics and they talk about setting bit 1,2,20 etc.
I dont understand how 0800000h can be bit 23.

They just endless sums up bitsets without explaining anything clear.
like cpuid, if eax==1 and edx==080000h how can 080000h be BIT 23?

Its confusing me a whole lot.
If i could understand bit 23 etc stuff i could then do something usefull with the information obtained
from bios.

Bios holds lots of interseting stuff, But in order to use it i need to understand it. ;-)

I hope i am not a complete moron ;-)




Title: Re: Bit format, cpuid bits hmm whats the diff 0-7 bit and how do i access it?
Post by: Mark Jones on March 08, 2005, 07:16:26 AM
Aaaha, you want to know if 0x800000h == 0b100000000000000000000000.


See this:
http://www.learn-programming.za.net/articles_decbinhexoct.html

and:
http://www.danbbs.dk/~erikoest/hex.htm
Title: Re: Bit format, cpuid bits hmm whats the diff 0-7 bit and how do i access it?
Post by: marco1974 on March 08, 2005, 08:40:37 AM
hello friends,

I have looked deeper into the intel docs: 24319102.pdf see page 158 the cpuid section.
ok.

eax=1
eax[3:0]  = stepping id
eax[7:4]  = model
eax[11:8]  = familly

Ok, lets try to learn something here!

eax= 32 bits register so 32 values of 1 bit can be placed in it.
Acording to the intel docs they use heximal to indicate a feature.

edx[012345678901234567890123456789012]  ; 32 values

Lets assume we have used cpuid and eax=1
To do something with the data we need to read EXACTLY x BYTES from eax or EDX!

Damm we have a reall challange here! read x bytes from 3 to 7 and place them in a db,dw so we can
pressent the user with some info.

How do i read a RANGE from a register like this????? (please answer this)

.data
result db ?

; lets asume the data we need to read is
;bytes : 4-8


; into = where to place result
; startoffset = [eax:11]
; endoffset = [eax:15]

proc ReadBytes , INTO:byte ,startoffset_in_reg32:dword,end_byte_offset

mov eax,byte ptr [eax+4] ; pos 4

read:
mov result,byte ptr eax
inc ecx
cmp ecx,end_byte_offset
mov byte ptr [eax+1] ; set next pos to read
jne read


I DONT KNOW HOW TODO THIS.


end ReadBytes


Thanx if u can help me.

If it works, i can write some system Info tool.

Title: Re: Bit format, cpuid bits hmm whats the diff 0-7 bit and how do i access it?
Post by: AeroASM on March 08, 2005, 11:04:22 AM
The CPUID  instruction returns edx and other registers filled with info.  At the fundamental level this info is sotred as a sequence of 32 bits, like this: 01110100010101001010011111100010. When writing, you normally use hexadecimal because it is shorter to write out.

If you are only interested in bits 3 to 7, do this:


;edx now contains info, of which we want bits 3 to 7
and edx,11111000b  ;this zeroes out all bits apart from 3 to 7.
;now we have the data in bits 3 to 7, but we want it in bits 0 to 4 so we can read it properly.
shr edx,3 ;shift the register right by 4 bits
;edx now contains what was previously in bits 3 to 7, now the stuff is in bits 0 to 4.
Title: Re: Bit format, cpuid bits hmm whats the diff 0-7 bit and how do i access it?
Post by: Tedd on March 08, 2005, 11:13:03 AM
It's not bytes - it's bits. (1 byte = 8 bits)

To get bits 4-7 of eax ...

* eax looks like this: [--------------------------------]
* but we want: [------------------------xxxx----] ==> [----------------------------xxxx]
* so..



.data?
my_eax DWORD ?

.code
mov [my_eax],eax        ;save the value, so we don't mess it up
shr eax,4                     ;mov the bits so that bit 4 goes to the place of bit 0 (the 'bottom')
and eax,0fh                 ;mask out all the other bits because we don't want them (0fh = 00001111 binary)
mov [cpu_model],eax   ;cpu_model now contains the required value :)
;now to get the others...


So you just have to shift by the right amount and then mask out the extra bits you don't want.
To get the stepping id, obviously you don't need to shift, so you just mask it; and family goes the same way as model.

I'd try reading up on binary representation and such, just to make sure you learn the tricks :U
Title: Re: Bit format, cpuid bits hmm whats the diff 0-7 bit and how do i access it?
Post by: AeroASM on March 08, 2005, 12:34:00 PM
To preserve a register, it is better to push/pop it:


;...get eax...
push eax
;...use eax...
mov eax,[esp] ;restore eax
;...use eax...
mov eax,[esp] ;restore eax
;...use eax....
pop eax ;restore eax
Title: Re: Bit format, cpuid bits hmm whats the diff 0-7 bit and how do i access it?
Post by: Tedd on March 09, 2005, 12:22:28 PM
Quote from: AeroASM on March 08, 2005, 12:34:00 PM
To preserve a register, it is better to push/pop it:

My point was to demonstrate what to do :P
And if you're repeatedly re-getting the value, then I'd say it's better to store it (either in a variable or a spare register.)
eg.
my_eax = eax
get stepping
eax = my_eax
get model
eax = my_eax
get family


Which I prefer to repeatedly push-popping.
Title: Re: Bit format, cpuid bits hmm whats the diff 0-7 bit and how do i access it?
Post by: AeroASM on March 09, 2005, 01:57:02 PM
But if eax has been pushed, to restore it you do not need to use another pop and another push, you can just use mov eax,[esp]
Title: Re: Bit format, cpuid bits hmm whats the diff 0-7 bit and how do i access it?
Post by: marco1974 on March 09, 2005, 08:57:30 PM
Thank All of You for the clear examples shown here!

I didn`t knew that you could use shr,4 and then mask em out!

Btw when using :
mov eax,010101010010111111h ; for example

shr eax,3                     ; is 0 also counted so the shr SHIFTS 4 places shown left here??
                                  ; its counted in c/c++ but in asm hmm dont know.                         


and eax,0fh                 ;0f = 16d so eax holds 16 values now. is this right?
                                 ; If it had more then 16 Bits they are NOW wiped by the
                                 ; AND Operator.


; is this right? It makes sence!
; if it is the case you can resize the contents of a register that holds data!!!!

I am assuming it, (hmm learning is exiting!)

I am glad with the quotes from all of you ;-)

Thanx!



     
Title: Re: Bit format, cpuid bits hmm whats the diff 0-7 bit and how do i access it?
Post by: GregL on March 09, 2005, 10:57:55 PM
You can also use RECORD and MASK. Read about it in the MASM Programmers Guide. I have an example of using them if you would like to see one.

Title: Re: Bit format, cpuid bits hmm whats the diff 0-7 bit and how do i access it?
Post by: AeroASM on March 10, 2005, 07:09:44 AM
shr eax,3 only shifts the register right by three bits.

and eax,0fh:

0Fh = 01111b

therefore only the last four bits (values) will be saved.
Title: Re: Bit format, cpuid bits hmm whats the diff 0-7 bit and how do i access it?
Post by: Tedd on March 10, 2005, 12:01:15 PM
Quote from: AeroASM on March 09, 2005, 01:57:02 PM
But if eax has been pushed, to restore it you do not need to use another pop and another push, you can just use mov eax,[esp]

True, but when learning it's a good idea to keep things simple. (Something about learning to walk before learning to run :P)


marco
Seriously, read up on binary representation and then on logical operations (and, or, xor). It'll make things a whole lot clearer.
Title: Re: Bit format, cpuid bits hmm whats the diff 0-7 bit and how do i access it?
Post by: marco1974 on March 10, 2005, 03:05:13 PM
Quote from: Greg on March 09, 2005, 10:57:55 PM
You can also use RECORD and MASK. Read about it in the MASM Programmers Guide. I have an example of using them if you would like to see one.

Yeah i would surely like that!
Title: Re: Bit format, cpuid bits hmm whats the diff 0-7 bit and how do i access it?
Post by: GregL on March 14, 2005, 03:38:30 AM
An example of using RECORD and MASK, not quite as handy as Bit Fields in C, but simplifies the process of using AND and SHR.


; CPUID.asm
; /SUBSYSTEM:CONSOLE
; Greg Lyon

.586
.model flat, stdcall
option casemap:none

;-------------------------------------------------
; Includes
;-------------------------------------------------
include windows.inc

include kernel32.inc
include masm32.inc
;include gel32.inc

includelib kernel32.lib
includelib masm32.lib
;includelib gel32.lib

;-------------------------------------------------
; Equates
;-------------------------------------------------
Cr                 EQU 13
Lf                 EQU 10

BLACK              EQU  0
BLUE               EQU  1
GREEN              EQU  2
CYAN               EQU  3
RED                EQU  4
MAGENTA            EQU  5
BROWN              EQU  6
LIGHTGRAY          EQU  7
DARKGRAY           EQU  8
LIGHTBLUE          EQU  9
LIGHTGREEN         EQU 10
LIGHTCYAN          EQU 11
LIGHTRED           EQU 12
LIGHTMAGENTA       EQU 13
YELLOW             EQU 14
WHITE              EQU 15
DEFAULT            EQU LIGHTGRAY

;-------------------------------------------------
; Records
;-------------------------------------------------

EAX_REC_1          RECORD \ 
                   b28_31a  : 4,    ; bit 28-31
                   ExtFam   : 8,    ; bit 20-27
                   ExtMod   : 4,    ; bit 16-19
                   b14_15a  : 2,    ; bit 14-15
                   ProcType : 2,    ; bit 12-13
                   Family   : 4,    ; bit 8-11
                   Model    : 4,    ; bit 4-7
                   Stepping : 4     ; bit 0-3
                 
EBX_REC_1          RECORD \
                   b8_31c   : 24,   ; bit 8-31
                   BrandID  :  8    ; bit 0-7
                                 
ECX_REC_1          RECORD \
                   b1_30c   : 31,   ; bit 1-30                                         
                   SSE3     : 1     ; bit 0
                 
EDX_REC_1          RECORD \ 
                   b27_31d  : 5,    ; bit 27-31
                   SSE2     : 1,    ; bit 26
                   SSE      : 1,    ; bit 25
                   b24d     : 1,    ; bit 24
                   MMX      : 1,    ; bit 23
                   b1_22d   : 22,   ; bit 1-22
                   FPU      : 1     ; bit 0
                   
;-------------------------------------------------
; Macros
;-------------------------------------------------
Color MACRO val:=<DEFAULT>
 
    cmp dwGotStdOutHandle, 0
    jne @F
        INVOKE GetStdHandle, STD_OUTPUT_HANDLE
        mov hStdOut, eax
        mov dwGotStdOutHandle, -1
    @@:           
    INVOKE SetConsoleTextAttribute, hStdOut, val
                                     
ENDM   

;-------------------------------------------------
    .DATA 
   
        Eax1       EAX_REC_1 <0>
        Ebx1       EBX_REC_1 <0>
        Ecx1       ECX_REC_1 <0>
        Edx1       EDX_REC_1 <0>
       
        dwMaxLevel DWORD 0
        dwProcSig  DWORD 0
        dwBrandID  DWORD 0
        dwGotStdOutHandle SDWORD  0
        hStdOut    DWORD   0   
       
        szBuf      BYTE 256 dup(?) 
         
        BrandStr   BYTE 48 dup(0)
        VendorStr  BYTE 13 dup (0)
                           
        szTitle    BYTE "CPUID", 0                       
        szNoCPUID  BYTE " Error: This CPU does not support the CPUID instruction.", 0                       
        szPak      BYTE "Press any key to continue...", 0   
       
        szBrandStr BYTE " Brand string:        ", 0           
        szBrandID  BYTE " Brand ID:            ", 0
                           
        szVendor   BYTE " Vendor ID string:    ", 0
        szMaxLevel BYTE " Maximum CPUID level: ", 0
        szStepping BYTE " Stepping:            ", 0
        szModel    BYTE " Model:               ", 0
        szFamily   BYTE " Family:              ", 0
        szProcType BYTE " Processor type:      ", 0
        szExtMod   BYTE " Extended model:      ", 0
        szExtFam   BYTE " Extended family:     ", 0
        szFPU      BYTE " FPU:                 ", 0   
        szMMX      BYTE " MMX:                 ", 0
        szSSE      BYTE " SSE:                 ", 0
        szSSE2     BYTE " SSE2:                ", 0
        szSSE3     BYTE " SSE3:                ", 0
       
        sz01h      BYTE "Intel Celeron processor", 0
        sz02h      BYTE "Intel Pentium III processor", 0
        sz03h      BYTE "Intel Pentium III Xeon processor", 0 
        sz6B1h     BYTE "Intel Celeron processor", 0
        sz04h      BYTE "Intel Pentium III processor", 0
        sz06h      BYTE "Mobile Intel Pentium III Processor M", 0
        sz07h      BYTE "Mobile Intel Celeron processor", 0
        sz08h      BYTE "Intel Pentium 4 processor", 0
        szF138h    BYTE "Intel Genuine processor", 0
        sz09h      BYTE "Intel Pentium 4 processor", 0
        sz0Ah      BYTE "Intel Celeron Processor", 0
        sz0Bh      BYTE "Intel Xeon processor", 0
        szF13Bh    BYTE "Intel Xeon processor MP", 0
        sz0Ch      BYTE "Intel Xeon processor MP", 0
        sz0Eh      BYTE "Mobile Intel Pentium 4 processor M", 0
        szF13Eh    BYTE "Intel Xeon processor", 0
        sz0Fh      BYTE "Mobile Intel Celeron Processor", 0
        szUnknown  BYTE "Unknown", 0
               
        szNotSupp  BYTE "Not supported", 0       
        szYes      BYTE "Yes", 0
        szNo       BYTE "No", 0
        szCrLf     BYTE Cr, Lf, 0

;-------------------------------------------------                         
    .CODE
   
start:

    invoke StdOut, ADDR szTitle
    invoke StdOut, ADDR szCrLf
    invoke StdOut, ADDR szCrLf
    ;------------------------------------
    ; Check for CPUID instruction support
    ;------------------------------------
    pushfd
    pop     eax
    xor     eax, 00200000h  ; flip bit 21
    push    eax
    popfd
    pushfd
    pop     ecx
    xor     eax, ecx        ; check if bit 21 was flipped
    jz      cpuid_supported
    jmp     no_cpuid           
       
cpuid_supported:

    ;------------------------------------
    ; Check for Brand String support
    ;------------------------------------
    invoke StdOut, ADDR szBrandStr
   
    mov eax, 80000000h
    cpuid
   
    .IF eax > 80000000h     
        ; Brand String is supported
        mov eax, 80000002h
        mov dword ptr [BrandStr+ 0], eax
        mov dword ptr [BrandStr+ 4], ebx
        mov dword ptr [BrandStr+ 8], ecx
        mov dword ptr [BrandStr+12], edx
        mov eax, 80000003h
        mov dword ptr [BrandStr+16], eax
        mov dword ptr [BrandStr+20], ebx
        mov dword ptr [BrandStr+24], ecx
        mov dword ptr [BrandStr+28], edx
        mov eax, 80000004h
        mov dword ptr [BrandStr+32], eax
        mov dword ptr [BrandStr+36], ebx
        mov dword ptr [BrandStr+40], ecx
        mov dword ptr [BrandStr+44], edx
                     
        invoke StdOut, ADDR BrandStr
                               
    .ELSE
        Color DARKGRAY
        invoke StdOut, ADDR szNotSupp
        Color LIGHTGRAY
       
    .ENDIF
     
     invoke StdOut, ADDR szCrLf   
   
    ;------------------------------------
    ; Check for Brand ID support
    ;------------------------------------
    invoke StdOut, ADDR szBrandID
    mov eax, 1
    cpuid
   
    mov dwProcSig, eax
    mov Ebx1, ebx
   
    mov eax, Ebx1
    and eax, MASK BrandID
    shr eax, BrandID
    .IF eax != 0
   
        ; Brand ID is supported
        mov dwBrandID, eax
           
        .IF dwBrandID == 01h
            invoke StdOut, ADDR sz01h
        .ELSEIF dwBrandID == 02h
            invoke StdOut, ADDR sz02h
        .ELSEIF dwBrandID == 03h
            .IF dwProcSig == 000006B1h
                invoke StdOut, ADDR sz6B1h
            .ELSE   
                invoke StdOut, ADDR sz03h
            .ENDIF   
        .ELSEIF dwBrandID == 04h
            invoke StdOut, ADDR sz04h
        .ELSEIF dwBrandID == 06h
            invoke StdOut, ADDR sz06h
        .ELSEIF dwBrandID == 07h
            invoke StdOut, ADDR sz07h
        .ELSEIF dwBrandID == 08h
            .IF dwProcSig == 00000F13h
                invoke StdOut, ADDR szF138h
            .ELSE
                invoke StdOut, ADDR sz08h
            .ENDIF   
        .ELSEIF dwBrandID == 09h
            invoke StdOut, ADDR sz09h
        .ELSEIF dwBrandID == 0Ah
            invoke StdOut, ADDR sz0Ah
        .ELSEIF dwBrandID == 0Bh
            .IF dwProcSig == 00000F13h
                invoke StdOut, ADDR szF13Bh
            .ELSE
                invoke StdOut, ADDR sz0Bh
            .ENDIF   
        .ELSEIF dwBrandID == 0Ch
            invoke StdOut, ADDR sz0Ch
        .ELSEIF dwBrandID == 0Eh
            .IF dwProcSig == 00000F13h
                invoke StdOut, ADDR szF13Eh
            .ELSE
                invoke StdOut, ADDR sz0Eh
            .ENDIF   
        .ELSEIF dwBrandID == 0Fh
            invoke StdOut, ADDR sz0Fh
        .ELSE
            invoke StdOut, ADDR szUnknown
        .ENDIF

    .ELSE
   
        Color DARKGRAY
        invoke StdOut, ADDR szNotSupp
        Color LIGHTGRAY
       
    .ENDIF
   
    invoke StdOut, ADDR szCrLf       
                       
    ;------------------------------
    ; CPUID Level 0
    ;------------------------------
    xor   eax, eax 
    cpuid           
 
    mov   dwMaxLevel, eax 
         
    ; Save vendor string, "GenuineIntel" or "AuthenticAMD"
    mov dword ptr [VendorStr+0], ebx   ; "Genu"
    mov dword ptr [VendorStr+4], edx   ; "ineI"
    mov dword ptr [VendorStr+8], ecx   ; "ntel"
       
    invoke StdOut, ADDR szVendor
    invoke StdOut, ADDR VendorStr
    invoke StdOut, ADDR szCrLf   
   
    invoke dwtoa, dwMaxLevel, ADDR szBuf
    invoke StdOut, ADDR szMaxLevel
    invoke StdOut, ADDR szBuf   
    invoke StdOut, ADDR szCrLf 
           
    ;------------------------------
    ; CPUID Level 1
    ;------------------------------
    mov eax, 1
    cpuid
         
    mov Eax1, eax
    mov Ebx1, ebx
    mov Ecx1, ecx
    mov Edx1, edx
    ;------------------------------
    mov eax, Eax1
    and eax, MASK Stepping
    shr eax, Stepping
    invoke dwtoa, eax, ADDR szBuf
    invoke StdOut, ADDR szStepping
    invoke StdOut, ADDR szBuf
    invoke StdOut, ADDR szCrLf
    ;------------------------------
    mov eax, Eax1
    and eax, MASK Model
    shr eax, Model
    invoke dwtoa, eax, ADDR szBuf
    invoke StdOut, ADDR szModel
    invoke StdOut, ADDR szBuf
    invoke StdOut, ADDR szCrLf
    ;------------------------------
    mov eax, Eax1
    and eax, MASK Family
    shr eax, Family
    invoke dwtoa, eax, ADDR szBuf
    invoke StdOut, ADDR szFamily
    invoke StdOut, ADDR szBuf
    invoke StdOut, ADDR szCrLf
    ;------------------------------
    mov eax, Eax1
    and eax, MASK ProcType
    shr eax, ProcType
    invoke dwtoa, eax, ADDR szBuf
    invoke StdOut, ADDR szProcType
    invoke StdOut, ADDR szBuf
    invoke StdOut, ADDR szCrLf
    ;------------------------------
    mov eax, Eax1
    and eax, MASK ExtMod
    shr eax, ExtMod
    invoke dwtoa, eax, ADDR szBuf
    invoke StdOut, ADDR szExtMod
    invoke StdOut, ADDR szBuf
    invoke StdOut, ADDR szCrLf
    ;------------------------------
    mov eax, Eax1
    and eax, MASK ExtFam
    shr eax, ExtFam
    invoke dwtoa, eax, ADDR szBuf
    invoke StdOut, ADDR szExtFam
    invoke StdOut, ADDR szBuf
    invoke StdOut, ADDR szCrLf
    ;------------------------------
    invoke StdOut, ADDR szFPU
    mov eax, Edx1
    and eax, MASK FPU
    shr eax, FPU
    .IF eax == 1
        invoke StdOut, ADDR szYes
    .ELSE
        invoke StdOut, ADDR szNo
    .ENDIF
    invoke StdOut, ADDR szCrLf
    ;------------------------------
    invoke StdOut, ADDR szMMX
    mov eax, Edx1
    and eax, MASK MMX
    shr eax, MMX
    .IF eax == 1
        invoke StdOut, ADDR szYes
    .ELSE
        invoke StdOut, ADDR szNo
    .ENDIF
    invoke StdOut, ADDR szCrLf
    ;------------------------------
    invoke StdOut, ADDR szSSE
    mov eax, Edx1
    and eax, MASK SSE
    shr eax, SSE
    .IF eax == 1
        invoke StdOut, ADDR szYes
    .ELSE
        invoke StdOut, ADDR szNo
    .ENDIF
    invoke StdOut, ADDR szCrLf
    ;------------------------------
    invoke StdOut, ADDR szSSE2
    mov eax, Edx1
    and eax, MASK SSE2
    shr eax, SSE2
    .IF eax == 1
        invoke StdOut, ADDR szYes
    .ELSE
        invoke StdOut, ADDR szNo
    .ENDIF
    invoke StdOut, ADDR szCrLf
    ;------------------------------
    invoke StdOut, ADDR szSSE3
    mov eax, Ecx1
    and eax, MASK SSE3
    shr eax, SSE3
    .IF eax == 1
        invoke StdOut, ADDR szYes
    .ELSE
        invoke StdOut, ADDR szNo
    .ENDIF
    invoke StdOut, ADDR szCrLf
    ;------------------------------
    jmp done
                     
no_cpuid:

    invoke StdOut, ADDR szNoCPUID
    invoke StdOut, ADDR szCrLf
   
done:

    ;invoke StdOut, ADDR szCrLf
    ;invoke StdOut, ADDR szPak
    ;invoke WaitKey
    invoke ExitProcess, 0
   
end start