I wonder if someone could share shorter way
to check for CPUID support.
Now I'm checking this way:
to check for CPUID support.
Now I'm checking this way:
mov eax,sbit(21) ;macro to generate value power of 2
pushfd
xor [esp],eax
popfd
pushfd
test [esp],eax
je @nocpuid
xor [esp],eax
;cpuid OK
popfd
.....
@nocpuid:
popfd
....
I found this somewhere on the net:
pushfd ; push eflags
pop eax ; move to eflags to aex
mov edx,eax ; make a copy
xor eax,200000h ; toggle the bit
push eax ; push copy of eflags
popfd ; check if CPUID flag could toggle
pushfd ; save it, so we can check it
pop eax ; get it
xor eax,edx ; did bit toggle?
jz end_label ; can't use CPUID instruction
; can use CPUID instruction
end_label:
push edx ; push origianl copy of EFLAGS
popfd ; restore original EFLAGS value
Thanks for replay.
The same size and IMHO bad disign to use edx for storing EFL, 'cause
if CPUID if OK then after check there would be most likely CPUID instruction
that would spoil edx, so edx needs additional presevation with EFL values.
Another try - more instructions but less in size:
The same size and IMHO bad disign to use edx for storing EFL, 'cause
if CPUID if OK then after check there would be most likely CPUID instruction
that would spoil edx, so edx needs additional presevation with EFL values.
Another try - more instructions but less in size:
pushfd ;1
mov eax,sbit(21);5
pushfd ;1
pop ecx ;1
xor ecx,eax;2
push ecx;1
popfd ;1
pushfd;1
pop ecx ;1
test ecx,eax ;2
popfd ;1
je @nocpuid
;here is code for cpuid
....
@nocpuid:
;code in case of absence of CPUID
just in case - here is sbit macro
;-------------------
sbit macro bitnum
;-------------------
LOCAL p2
p2=1
rept bitnum
p2=p2+p2
endm
exitm %p2
endm
Why write a macro for that, when there is one built in?
1 SHL 21
Mirno
1 SHL 21
Mirno
It's matter of personal taste.
sbit wasn't written for this particular case.
I prefer see syntax that stress what is important to me,
not expression with the same result but less clear.
Let me give you example
I need load value that contains bit 30 and 7 set
I could write:
push (1 shl 30) or (1 shl 7)
the other way I could write:
push sbit(30) or sbit(7)
Last one more compehencive to me in regard of what it means
when I look at source.
sbit wasn't written for this particular case.
I prefer see syntax that stress what is important to me,
not expression with the same result but less clear.
Let me give you example
I need load value that contains bit 30 and 7 set
I could write:
push (1 shl 30) or (1 shl 7)
the other way I could write:
push sbit(30) or sbit(7)
Last one more compehencive to me in regard of what it means
when I look at source.
Stupid idea: how 'bout SEH?
But aren't we at the point yet where we can assume >= late 486 CPUs? :)
But aren't we at the point yet where we can assume >= late 486 CPUs? :)
How about this?
pushfd ; 1
or byte [esp+2],32 ; 5
popfd ; 1
pushfd ; 1
pop eax ; 1
shr eax,22 ; 3
jae no_cpuid ; 2
; ...
no_cpuid:
Sephiroth3,
That's good one :)
I'd choose jnc mnemonic for clarity
That's good one :)
I'd choose jnc mnemonic for clarity
About size calculation,
1. About jcc - I treat is as x not as 2, 'cause it's not clear how
long block working with "cpuid ok " could be. And so I don't count it at all
in all versions.
2. I would like make sure that EFL restored, so I'd add 2 bytes
for restoring EFL.
Alltogether with the correction it makes 14 bytes wich is 3 bytes
shorter than my last version. Good result.
1. About jcc - I treat is as x not as 2, 'cause it's not clear how
long block working with "cpuid ok " could be. And so I don't count it at all
in all versions.
2. I would like make sure that EFL restored, so I'd add 2 bytes
for restoring EFL.
Alltogether with the correction it makes 14 bytes wich is 3 bytes
shorter than my last version. Good result.