Bit format, cpuid bits hmm whats the diff 0-7 bit and how do i access it?

Started by marco1974, March 08, 2005, 06:17:04 AM

Previous topic - Next topic

marco1974

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.









Petroizki

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.

donkey

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
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

marco1974

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 ;-)





Mark Jones

"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

marco1974

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.


AeroASM

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.

Tedd

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
No snowflake in an avalanche feels responsible.

AeroASM

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

Tedd

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.
No snowflake in an avalanche feels responsible.

AeroASM

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]

marco1974

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!



     

GregL

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.


AeroASM

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.

Tedd

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.
No snowflake in an avalanche feels responsible.