7
\$\begingroup\$

These are the three steps that need to be taken in order to successfully activate Long Mode. Error reporting is sparse as most real hardware for developing an OS is 64 bit but probably still a good idea to implement this verification procedure.

I did a little tweaking of some of the examples that can be found on the web either in whole or in part and believe 74 bytes might be as tight as it can get.

 PageZero equ 0xb800
 ID equ 0b100000
; AMD 24592 Rev 3.14 2007 Feature detection. Section 3.6 pg 74
; ------------------------------------------------------------
 ; A: Test if CPU supports CPUID
 pushfd ; Save a current copy of flags
 ; Create a simplified pointer that becomes essentially SS:BX
 push ss
 mov bx, sp ; BX will point to bits 23-16 of EFLAGS
 pop ds
 ; Read flags, toggle (ID) and write back to flags.
 pushfd ; Get another copy of EFLAGS 
 or byte [bx], ID ; Toggle bit 21 (ID) [bit 5 of BX]
 mov al, [bx] ; Save a copy
 popfd ; Write value back to EFLAGS
 ; Read flags again and if ID remains inverted, then processor supports CPUID.
 pushfd
 pop dx ; DX = Bits 15 - 0 of EFLAGS
 pop dx ; DX = Bits 16 - 31
 popfd ; Restore flags to original values
 xor al, dl ; Bit 4 of AL & DL is (ID)
 jz TstExt
; As this error is very improbable, near center bottom there will be an uppercase "E"
; yellow on red, with two red flashing bars on each side.
FncErr: mov di, (22*80+39)*2 ; Point to center position of 21th row in video
 mov ax, PageZero ; Page 0 of 80x26x16 (Mode 3)
 mov es, ax
 mov eax, 0x2e4684b1 ; This makes the desired character combination work
 stosd
 stosw
 cli
 hlt
 jmp $ - 1 ; Just hang.
 ; B: Are extended functions supported
TstExt: 
 mov eax, 0x80000000
 push eax
 cpuid ; Extended function limit
 pop edx
 cmp eax, edx
 jb FncErr
 ; C: Does processor support Long Mode.
 mov al, 1 ; Set EAX = 0x80000001
 cpuid
 bt edx, 29 ; 64 bit available if bit is on.
 jnc FncErr
Reinderien
70.9k5 gold badges76 silver badges256 bronze badges
asked Nov 10, 2018 at 4:38
\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

Documentation for this flag reads:

If a software procedure can set and clear this flag, the processor executing the procedure supports the CPUID instruction

This clearly means that the flag does not have a defined value. It could be OFF or ON at any time!

  • Where your comment says that you "Toggle bit 21 (ID)", the instruction actually sets the bit. I don't think that would be too useful since you don't use the pre-existing value of this bit.

  • When you exclusive or XOR the registers AL and DL, you should prudently mask away the 7 remaining bits.

All the forementioned boils down to the fact that the final test (notice the typo in the comment; should be bit 5)

xor al, dl ; Bit 4 of AL & DL is (ID)
jz TstExt

will always check out fine.


Although your method to get a DS:BX pointer is quite ingenious, I prefer using [bp-2] as you can see in below code.

 mov bp, sp
 pushfd
 mov al, [bp-2] ;Pre-existing value
 xor byte [bp-2], ID ;Toggle bit 21
 popfd
 pushfd
 mov ah, [bp-2] ;Hopefully changed value
 popfd
 and ax, (ID<<8)+ID ;Mask off unimportant bits
 cmp al, ah
 jne TstExt
FncErr:

I omitted preserving the ID bit as per definition this should not be necessary.


FncErr: mov di, (22*80+39)*2 ; Point to center position of 21th row in video

The address points to the 23rd row.


cmp eax, edx <<< EDX=0x80000000
jb FncErr

Are you sure the service can't report EAX=0x80000000 ?
Perhaps it could be better to bail out with:

jbe FncErr

Now you're certain that leaf 0x80000001 exists.


Reaching leaf 0x80000001 through mov al, 1 will continue to work for as long as the manufacturer doesn't create some high numbered leafs (0x80000100 and up). You have to ask yourself how future-proof that you want your program to be!

Fifoernik
6144 silver badges9 bronze badges
answered Nov 11, 2018 at 22:08
\$\endgroup\$
1
  • \$\begingroup\$ Thanks for the critique and your comments do speak to making the code more predictable. Obviously, it can't be known by the example, but my bootloader sets BP so I would have to essentially create a procedure frame. That being said, I was surprised to find your example is only 2 bytes larger than mine, which at a glance wasn't something I'd expected. \$\endgroup\$ Commented Nov 11, 2018 at 23:49

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.