I have finaly figured out what i wan't to do, and thats about it.
First step involves identifying the cpu (in real mode/boot time) but i haven't been able to find much on google.
Basicly i just wanted to ask if anyone knows of any good recourses.
Thanks
edit: You are probably thinking, what an idiot, just use the CPUID, but when reading the manual, allthough it doesn't state that it can't be used in real mode, it refers only to 32bit registers, so this is a bit confusing.
Identify this!
Identify this!
This was supposed to be a cool signature...
Hi,
This means that (for e.g.) in real mode you can use an instruction like "lea eax,[ecx*4+edx]", even though the 16-bit version of the instruction (e.g. "lea ax,[cx*4+dx]") won't work (it's not a valid addressing mode for 16-bit code).
You may want code to determine if the CPU supports 32-bit registers, etc. Here's some:
The next step would be to determine if the CPUID instruction is supported or not. For this I setup an invalid opcode exception and execute CPUID to see if I get an invalid opcode exception or not. The normal method recommended by Intel (checking if the ID bit in EFLAGS can be modified) doesn't work on some CPUs (some CPUs, e.g. NexGen, support CPUID but don't support the ID bit in EFLAGS).
Also, for some CPUs (e.g. Cyrix) the CPUID instruction needs to be enabled before it's used, so if CPUID isn't supported you'd check if the CPU might be a Cyrix (using the "5/2" method) and then determine if it's an IBM "Blue Lightning" or a Cyrix (the IBM "Blue Lightning" chip supports MSRs while Cyrix chips don't).
If it is a Cyrix there's I/O ports to mess with. These I/O ports can return the "Cyrix CPU identification" information and (for later Cyrix CPUs) the I/O ports can also enable the CPUID instruction (and do other things).
In general, how much hassle CPU identification is will depend on which CPUs you support (e.g. it's easier if you don't support Pentium or older CPUs) and if you want high quality code or "average" code...
IMHO at a minimum you need a reliable set of feature flags to determine if the CPU/s support a certain feature or not. This means getting the dodgy feature flags from CPUID and correcting them.
Cheers,
Brendan
You can use 32-bit registers and 32-bit addressing in real mode, just like you can use 16-bit registers and 16-bit addressing in 32-bit protected mode. The limitations are that you need a CPU capable of operating on 32-bits (it won't work for 80286 or older CPUs) and (for 32-bit addressing in real mode) the segment limits are still 64 KB.Zacariaz wrote:It's embaresing enough as it is but it doesn't really make sence, 16 bit real mode and 32 bit registers? There must be some limitations.
This means that (for e.g.) in real mode you can use an instruction like "lea eax,[ecx*4+edx]", even though the 16-bit version of the instruction (e.g. "lea ax,[cx*4+dx]") won't work (it's not a valid addressing mode for 16-bit code).
You may want code to determine if the CPU supports 32-bit registers, etc. Here's some:
Code: Select all
;The first step is to find out if the CPU is an original 8086. This is necessary
;because the other tests will crash an 8086. This test simply determines
;if bit 15 of the flags register is set, as this bit is hardwired to 1
;on an 8086 and hardwired to 0 on everything after it.
cli
pushf
pop ax ;ax = original flags
test ah,0x80 ;Is bit 15 set?
jne .CPUold ; yes, old 8086!
;The next step is to find out if the CPU is 32 bit (80386 or later). This
;test just checks to see if the IOPL bits (bits 12 and 13) can be changed.
;On CPUs that don't support 32 bit protected mode these bits aren't
;implemented in the CPU.
xor ah,0x30 ;ax = flags with modified IOPL bits
push ax ;Save flags
popf ;Load flags
pushf ;Save modified flags
pop bx ;bx = modified flags
xor ax,bx ;ax = flags with changed bits set
test ah,0x30 ;Did IOPL bits change?
jne .CPUold ; no, not a 32 bit CPU
CPU 386
;Make sure ESP is the same as SP.
movzx esp,sp
;Now we know that the CPU is at least an 80386, so we can use
;eflags (the 32 bit version of the flags register) to see if it's
;an 80486 or later. Here we see if the bit that enables/disables
;the alignment check feature can be modified. Alignment check
;didn't exist before 80486, so this bit can't be changed on
;older CPUs.
pushfd
mov eax,[esp] ;eax = original eflags
xor eax,0x00040000 ;Invert AC flag
push eax ;Store new eflags on stack
popfd ;Read new eflags
pushfd ;Store modified eflags
pop ebx ;ebx = flags after changing
xor eax,ebx ;If bits changed set them, else clear them
popfd ;Restore original eflags
test eax,0x40000 ;Is alignment check supported?
jne .CPUold ; no, must be older than an 80486
;After all that we know BCOS will be able to run on the CPU. We restore
;eflags to a known state and return.
push dword 0x00000202 ;Push default eflags (interrupts & reserved bit)
popfd
ret
;Error Handler
;_______________________________________________________________________________
;This little bit of code is responsible for displaying the "Your
;CPU is too old" error message and halting.
.CPUold:
sti
mov si,badCPUstring
jmp abortBoot
Also, for some CPUs (e.g. Cyrix) the CPUID instruction needs to be enabled before it's used, so if CPUID isn't supported you'd check if the CPU might be a Cyrix (using the "5/2" method) and then determine if it's an IBM "Blue Lightning" or a Cyrix (the IBM "Blue Lightning" chip supports MSRs while Cyrix chips don't).
If it is a Cyrix there's I/O ports to mess with. These I/O ports can return the "Cyrix CPU identification" information and (for later Cyrix CPUs) the I/O ports can also enable the CPUID instruction (and do other things).
In general, how much hassle CPU identification is will depend on which CPUs you support (e.g. it's easier if you don't support Pentium or older CPUs) and if you want high quality code or "average" code...
IMHO at a minimum you need a reliable set of feature flags to determine if the CPU/s support a certain feature or not. This means getting the dodgy feature flags from CPUID and correcting them.
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.