; Boot sector authoring example by Gareth Owen (gaz@athene.co.uk)
; This should be accompanied with an article explaining bootsectors

[BITS 16]       ; the bios starts out in 16-bit real mode
[ORG 0]		; Data offset = 0

jmp start       ; skip over our data and functions, we cannot execute data :-),
                ; well, you can, but i am not held responsible for the results :)

; -------------------------------------
; Data used in the boot-loading process
; ------------------------------------------------------------------------
        bootdrv         db 0
        bootmsg         db 'Gareth Owen',39,'s Boot Sector Example',13,10,0

        rebootmsg    db 'Press any key to reboot',13,10,0

        ; these are used in the processor identification
        processormsg    db 'Checking for 386+ processor: ',0
        need386         db 'Sorry... 386+ required!',13,10,0
        found386        db 'Found!',13,10,0

	whatever	db 'Insert your code to do something here',13,10,0

;*******************************************
; Functions we are going to use ...
;*******************************************
        detect_cpu:
                mov si, processormsg    ; tell the user what we're doing
                call message

                ; test if 8088/8086 is present (flag bits 12-15 will be set)
                pushf                   ; save the flags original value
                
                xor ah,ah               ; ah = 0
                push ax                 ; copy ax into the flags
                popf                    ; with bits 12-15 clear
                
                pushf                   ; Read flags back into ax
                pop ax       
                and ah,0f0h             ; check if bits 12-15 are set
                cmp ah,0f0h
                je no386                ; no 386 detected (8088/8086 present)

                ; check for a 286 (bits 12-15 are clear)
                mov ah,0f0h             ; set bits 12-15
                push ax                 ; copy ax onto the flags
                popf
                
                pushf                   ; copy the flags into ax
                pop ax
                and ah,0f0h             ; check if bits 12-15 are clear
                jz no386                ; no 386 detected (80286 present)
                popf                    ; pop the original flags back
                
                mov si, found386
                call message
                
                ret                     ; no 8088/8086 or 286, so ateast 386
         no386:
                mov si,need386          ; tell the user the problem
                call message
                jmp reboot              ; and reboot when key pressed
                     
;       ********************************************************************
        message:                        ; Dump ds:si to screen.
                lodsb                   ; load byte at ds:si into al
                or al,al                ; test if character is 0 (end)
                jz done
                mov ah,0eh              ; put character
                mov bx,0007             ; attribute
                int 0x10                ; call BIOS
                jmp message
        done:
                ret
;       ********************************************************************
        getkey:
                mov ah, 0               ; wait for key
                int 016h
                ret

;       ********************************************************************
        reboot:
                mov si, rebootmsg       ; be polite, and say we're rebooting
                call message
                call getkey             ; and even wait for a key :)

                db 0EAh                 ; machine language to jump to FFFF:0000 (reboot)

                dw 0000h
                dw 0FFFFh
                ; no ret required; we're rebooting! (Hey, I just saved a byte :)
                
; *******************************************
; The actual code of our boot loading process
; *******************************************
start:
        mov ax,0x7c0    ; BIOS puts us at 0:07C00h, so set DS accordinly
        mov ds,ax       ; Therefore, we don't have to add 07C00h to all our
data

        mov byte [bootdrv], dl ; quickly save what drive we booted from

        cli             ; clear interrupts while we setup a stack
        mov ax,0x9000   ; this seems to be the typical place for a stack
        mov ss,ax
        mov sp,0xffff   ; let's use the whole segment.  Why not?  We can :)
        sti             ; put our interrupts back on
        
        ; Interestingly enough, apparently the processor will disable 
        ; interupts itself when you directly access the stack segment!
        ; Atleast it does in protected mode, I'm not sure about real mode.
        
        mov si,bootmsg  ; display our startup message
        call message

        call detect_cpu ; check if we've got a 386

        mov si,whatever  ; tell the user we're not doing anything interesting here
        call message
        call getkey
	
	call reboot

        times 510-$ db 0
        dw 0xAA55
