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.
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.
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
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 ;-)
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
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.
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.
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
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
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.
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]
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!
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.
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.
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)
marcoSeriously, read up on binary representation and then on logical operations (and, or, xor). It'll make things a whole lot clearer.
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!
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