CPU Detection Algorithms
- ChosenOreo
- Member
- Posts: 25
- Joined: Sun May 29, 2011 5:16 pm
- Location: Inside A Computer
- Contact:
CPU Detection Algorithms
I've added a wiki page at User:ChosenOreo/CPU_Detection detailing different ways I detect various CPUs. I've only just started it, can't really do much on my phone right now but I'll probably add the rest of it tomorrow when I get on my computer. Right now I have detecting things lower than an 80286, (currently only) 8088/8086/80188/80186/V20/V30/V40/V50.
If you happen to know any other algorithms for detecting CPUs it'd be greatly appreciated. Some of the stuff I'm currently looking for include detecting if there is a coprocessor (x87-series, 8089, etc..), and getting the stepping information for the processor. I know you can reset the computer and get the values from the EDX register on 80386+, but I was wondering if there was any way to get the stepping info on 8086 through 80286.
Any feedback on my page and help with the two things listed above would be great!
- Adrian
If you happen to know any other algorithms for detecting CPUs it'd be greatly appreciated. Some of the stuff I'm currently looking for include detecting if there is a coprocessor (x87-series, 8089, etc..), and getting the stepping information for the processor. I know you can reset the computer and get the values from the EDX register on 80386+, but I was wondering if there was any way to get the stepping info on 8086 through 80286.
Any feedback on my page and help with the two things listed above would be great!
- Adrian
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: CPU Detection Algorithms
Div tests are good to tell apart brands of CPUs.
-
- Member
- Posts: 5513
- Joined: Mon Mar 25, 2013 7:01 pm
Re: CPU Detection Algorithms
The 386 is the first CPU to provide stepping information in a standard way. For all prior CPUs, you must use bugs or small differences in behavior to tell them apart.ChosenOreo wrote:I know you can reset the computer and get the values from the EDX register on 80386+, but I was wondering if there was any way to get the stepping info on 8086 through 80286.
I'm curious to see what information you have about getting the stepping from a 386/486. I know of at least two methods, but neither is 100% reliable.
Re: CPU Detection Algorithms
0x40 * 0x40 != 0, so other register should be used in lines 2-3, shouldn't it? Another option: you can just remove line 2.Code: Select all
xor al, al mov al, 0x40 mul al jz Cpu_Is_NEC
-
- Member
- Posts: 5513
- Joined: Mon Mar 25, 2013 7:01 pm
Re: CPU Detection Algorithms
The zero flag is undefined after mul. That code relies on differences in undefined behavior to detect the CPU.
Re: CPU Detection Algorithms
Code: Select all
Cpu86 = 0
Cpu286 = 4
Cpu386 = 8
Cpu486 = 12
Cpu586 = 16
;-------------------------------------
FpuNone = 0
FpuYes = 10h
FpuEmul = 50h
;-------------------------------------
call GETCPU ; AX=CPU
call GETFPU ; DX=FPU
;-------------------------------------
GETCPU: mov ax, Cpu86
xor bx, bx
push bx
popf
pushf
pop bx
and bh, 0F0h
cmp bh, 0F0h
je short CPUOK
;-------------------------------------
mov ax, Cpu286
push 7000h
popf
pushf
pop bx
and bh, 70h
jz short CPUOK
;-------------------------------------
mov ax, Cpu386
mov edx, esp
and esp, 0FFFCh
pushfd
pop ebx
mov ecx, ebx
btc ebx, 18
push ebx
popfd
pushfd
pop ebx
push ecx
popfd
mov esp, edx
cmp ecx, ebx
jz short CPUOK
;-------------------------------------
mov ax, Cpu486
btc ecx, 21
push ecx
popfd
pushfd
pop ebx
cmp ebx, ecx
jnz short CPUOK
;-------------------------------------
mov ax, Cpu586
;-------------------------------------
CPUOK: mov bp, ax
ret ; AX=Cpu
;------------------------------------------------------------------------------
GETFPU: mov dx, FpuNone
mov BYTE PTR cs:[F1], 90h
mov BYTE PTR cs:[F2], 90h
F1: finit
F2: fstcw WORD PTR[FLAGS]
cmp BYTE PTR[FLAGS+1], 3
jnz short FPUOK
;-------------------------------------
mov dx, FpuYes
cmp ax, Cpu86 ; No emulation for 8086
jz short FPUOK
;-------------------------------------
smsw bx
shr bx, 1
and bx, 3
cmp bx, 2 ; Bit 2=1 -> Emul
jnz short FPUOK
;-------------------------------------
mov dx, FpuEmul
;-------------------------------------
FPUOK: ret ; DX=FPU
FLAGS DB 0, 0, 0, 0
- ChosenOreo
- Member
- Posts: 25
- Joined: Sun May 29, 2011 5:16 pm
- Location: Inside A Computer
- Contact:
Re: CPU Detection Algorithms
Thanks for all the comments guys!
However, as stated on his page, there are some times where that code shouldn't be executed as some BIOSes ignore the A20 line, while others have 2 copies of the code at both locations.
I was browsing the internet at one point for algorithms and I came across a few assembly files (sorry, can't seem to find them right now.. will keep looking!) that got stepping on 8086 and 80286, but nothing for the 80186 series. In those files, however, there were still a few steppings missing (from what I've read at least). I'll try to add links to them if I find them.
Edit: Through some deeper digging, I found an old NEC documentation that said that a MUL operation leaves the zero flag undefined. But, I did find a pdf with another way to detect it (rep lods bug). I'll be looking at that and incorporating it into the CPU Detection page as well.
Again, thanks everyone for comments!
- Adrian
I hadn't even heard about that before. Thanks for the link.. will be reading it!Combuster wrote:Div tests are good to tell apart brands of CPUs.
I rely on a method I learned about from Robert Collin's great article where you use a (bug?) where you can change the reset vector to point to your code (due to an inconsistency with the A20 line). Immediately after doing that, the computer is reset and you have some stepping information in the EDX register.Octocontrabass wrote:I'm curious to see what information you have about getting the stepping from a 386/486. I know of at least two methods, but neither is 100% reliable.
However, as stated on his page, there are some times where that code shouldn't be executed as some BIOSes ignore the A20 line, while others have 2 copies of the code at both locations.
I was hoping someone wouldn't say that.Octocontrabass wrote:For all prior CPUs, you must use bugs or small differences in behavior to tell them apart.
I was browsing the internet at one point for algorithms and I came across a few assembly files (sorry, can't seem to find them right now.. will keep looking!) that got stepping on 8086 and 80286, but nothing for the 80186 series. In those files, however, there were still a few steppings missing (from what I've read at least). I'll try to add links to them if I find them.
On all Intel documentation I've seen, the zero flag is undefined after a mul operation. On NECs (according to Robert Collins again..), however, the zero flag is set to what the result is. In the code, the xor operation sets the zero flag. At the mul operation, Intel CPUs will leave the flag alone while the NEC CPUs will, in this case, clear it. Then we just check the flag to see if we're a NEC or an Intel.Nable wrote:0x40 * 0x40 != 0, so ther register should be used in lines 2-3, shouldn't it? Another option: you can just remove line 2Code: Select all
xor al, al mov al, 0x40 mul al jz Cpu_Is_NEC
Edit: Through some deeper digging, I found an old NEC documentation that said that a MUL operation leaves the zero flag undefined. But, I did find a pdf with another way to detect it (rep lods bug). I'll be looking at that and incorporating it into the CPU Detection page as well.
Thanks for showing that! However, being a bit paranoid, I read somewhere that a finit can lock up some computers if an x87 coprocessor isn't there. Do you know if there's any truth to that?freecrac wrote:Code: Select all
...
Again, thanks everyone for comments!
- Adrian
Re: CPU Detection Algorithms
Hi,
Cheers,
Brendan
I think you're missing the simplest and most powerful technique: install an invalid opcode handler and see which opcodes are invalid. If "smsw" doesn't work then it's older than 80286, if "mov eax,cr3" doesn't work then it's older than 80386, if "invlpg" doesn't work it's older than 80486, if "cpuid" doesn't work then it's older than Pentium, etc.ChosenOreo wrote:Any feedback on my page and help with the two things listed above would be great!
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
- ChosenOreo
- Member
- Posts: 25
- Joined: Sun May 29, 2011 5:16 pm
- Location: Inside A Computer
- Contact:
Re: CPU Detection Algorithms
I do that for my detection of 286/386/486, I just haven't added it to the page yet. Thanks for the comment though!Brendan wrote:I think you're missing the simplest and most powerful technique: install an invalid opcode handler and see which opcodes are invalid.
- Adrian
Re: CPU Detection Algorithms
I have not found a good manual for 80186 but I guess it is not possible to use an invalid opcode handler if the CPU is older than 80286. For newer CPUs, this is an excellent method.Brendan wrote:install an invalid opcode handler and see which opcodes are invalid. If "smsw" doesn't work then it's older than 80286
Just a historical side note, the "smsw instruction starts with "0F" and I we had a really ancient 8086 CPU, this would be "pop cs".
Re: CPU Detection Algorithms
No sorry, i do not know that. I used it only together with a 80286 CPU and with the emulator "EM87.COM" (EM87 V1.2 9/08/89 from Ron Kimball).ChosenOreo wrote:Thanks for showing that! However, being a bit paranoid, I read somewhere that a finit can lock up some computers if an x87 coprocessor isn't there. Do you know if there's any truth to that?
Dirk
-
- Member
- Posts: 5513
- Joined: Mon Mar 25, 2013 7:01 pm
Re: CPU Detection Algorithms
The BIOS has a long-forgotten "fast reset" function that does a far jump to whatever address you'd like. It's intended for 286 operating systems, so it should be supported by all 386 and 486 BIOSes. You can use it to prevent the computer from rebooting in case your attempt to move the reset vector fails. (One BIOS does a near jump instead of a far jump, so you'll need to keep that in mind when you write your code.)ChosenOreo wrote:However, as stated on his page, there are some times where that code shouldn't be executed as some BIOSes ignore the A20 line, while others have 2 copies of the code at both locations.
It's also useful for getting the CPU signature, since most BIOSes won't modify EDX before jumping.