CPU Detection
The first step of our Init file is to detect the CPU of the PC running our OS. This is very well documented in Intel's Technical Manual. I recommend that you read that because what I explain is pretty much the same but only what we essentially need. First of all we need to know if we have a 386 or higher. That is easy, but detecting the accurate CPU itself involves more code. I will only do this for Intel type. You can find it for AMD in their homepage. Believe me, detecting the Intel CPU itself is a pain in the neck. So here it is.
For i386 CPU detection
According to the Intel technical manual, bit 12-15 of the FLAG Register in a 8086 processor is always set and in a 80286 processor is always clear. So that means if we try to clear (set it to 0) these bits of the FLAGS in an 8086 the processor would set (set it to 1) it back. Now, if we try to set it in a 80286 processor, the CPU would clear it. When we try to do that and if both of these doesn't happen, than means you do not have either a 8086 and 80286. We must have some other higher processor (80386 or higher). So here goes the code for that:
;******Intel 86/286 processor check*****
Checkfor86:
push bp
mov bp, sp
cli
pushf
; Save the original flags first because we are going to alter it
pushf
pop ax
and ax,0x0FFF
; Clear 12-15 bits of the register
push ax
popf
; Try to clear 12-15 bits of the flag
pushf
pop ax
; Store the Result in AX[for comparision]
and ax,0xF000
; See if 12-15 in AX is clear
cmp ax,0xF000
mov BYTE [cpucheck], 1
; If No, it is a 86/88 processor and
je End
; jump to the end
Checkfor286:
pushf
pop bx
; Store the result in BX[for comparision]
or bx,0x7000
; Set the 12-15 bits of the register
push bx
; Try to Set 12-15 bits of the flag
popf
pushf
pop bx
; Store the result in BX[for comparision]
test bx,0x7000
; See if 12-15 in BC is set
mov BYTE [cpucheck], 2
; turn on the 286
je End
; If it was clear, It is a 286 jump to end
; If it was set, go on to Check_for_386
popf ; Restore the original value
mov BYTE [cpucheck], 3
; Since we are here, that means it is at least a 386
End:
mov sp, bp
pop bp
sti
retn
This only does one thing. This checks to see if the processor is at least a 386. In your INIT, you could call this function and later check the "cpucheck" variable to see if it is 3 or above. If it is, then you are good to go on. You could combine the sections "Checkfor86" and "Checkfor286" to one section. If you look carefully, you will see that I am using two different registers (AX and BX) for bit manipulation. The only thing different is the way they are manipulated (one is ORd and other is ANDd). When you do anything, make sure you are not using any 32-bit registers in this function. Now the fun part is, when you want to see what actual type of CPU they have. The below section only works for an INTEL type CPU.
For More Information about CPU
According to the Intel Manual, if the CPU supports the instruction CPUID, then more information about the CPU can be obtained easily by looking at the 32 bit registers. There is a reason why I said "If the CPU supports CPUID" because all processors doesn't. Every type of processors up to 386 (including 386) doesn't and only few of the 486 supports this instruction. And, all from 586 and above supports CPUID. So that means in addition to the above code, you have to write some more code ( a lot more) to see if the processor is a 486. If it is a 486 (or above), then you have check to see if it supports CPUID instruction. If it does, then you are good to go on to next stage. I am not going to give you the code for that but I will tell you how to do that. According to the Intel technical manual, the bit number 18 (AC Bit) in the EFLAG Register in a 386 processor cannot be set. It can only be used in a 486 processor to generate alignment faults. If we successfully toggle that bit, that means it is a 486+ processor. Now we check if this processor support CPUID instruction by toggling bit number 21 in EFLAGS. If it does toggle, then it supports the instruction and we are good to move on. So, go do that now and if that works read on to the next paragraph.
Before you use this instruction, certain registers has to have certain value. Then after the call to this instruction, some of these registers will be filled with values that identify the CPU, FPU and other things about the current processor. This will only work if the CPU is from Intel. Of course the AMD also support this instruction but the values will be different for different processor. Now, you will be saying how will I get to know what vendor is this processor from (INTEL, AMD and Others). Well, when the first time you use the CPUID instruction with the EAX register ZERO, the CPUID returns the "VendorString" in EBX, EDX and ECX. If the vendor string is equal to "GenuineIntel", then you have the processor from Intel. Now after the first call, the EAX register will contain the number of times you can call the CPUID instruction. For example if the first call returns '2' in EAX, that means you can call it two more times. Once with '1' in EAX and the last time with '2' in EAX. After each time, you will get different results indicating different information about CPU. The below table give you the result of calling CPUID instruction second time (with '1' in EAX). The table tells you what value to set to registers and what will be the result after the call. Intel Technical Manual goes in depth and tells you the Processor Family and Model Number of each of their processors. Also, if you want to know more about CPU like, the Cache size, Frequency, FPU type, you have to call it additional times with additional parameters. Look in the Intel Technical Manual for more information. For our purpose, this is more than enough.
Man, What is that? From the picture it clear what is going to be what. All you need to know look is at the Processor Type, Family Code, and Model#. Table 2 below tells you about Processor Type and Table 3 is a long list of what the other two variables mean.
The tables above are taken straight from the Intel Technical Manual and use it to see what the CPU is. Although this is not necessary for operating system development, detecting the MMX and SIMD support is essential for graphical user interface system development. If you look in the last table, you will see that Pentium 4 systems have the same ID(s). The way you detect is by getting Cache information by using the instruction again with a '2' in EAX. I won't go into that because we do not need that.