V40 Motherboard Project

Introduction:

This is a V40-70208 motherboard that is PC compatible built to fit an ATX case. The reason for using the V40 is that all the peripherals are integrated into the processor. Only the system memory, the keyboard port, and the hard drive have to be added.


Downloads:

BIOS V40 Bios 5 Jun 2021 -LCD Screen

BIOS V40 Bios 19 Jun 2021 -CGA

BIOS V40 BIOS 21 Jul 21 -CGA includes JMP Far code at 0xFFFF0

Raspberry PI 32K ROM uploader RPI 32K ROM Writer 21 Jul 21

Most my BIOS files are written for my homemade 32 k EEPROM writer. The JMP FAR 0xF800:0x0000 code is automatically inserted at Address 0xFFFF0 by my writer. If your using a standard EEPROM writer you will need to make sure that the BIOS file has the JMP code in the correct place.

To make my BIOS files 32k with the jump code add the follow to the end of the code

END_OF_CODE:

TIMES 0X7FF0-(END_OF_CODE - START) DB 0X00

JMP 0XF800:0X0000

DB 'XXX2021', 0X00, 0X00, 0X00, 0X00


Third party downloads:

BIOS hakfoo / v40-bios · GitLab 21 Jul 21 -VGA

Code:

This is pulled right from my BIOS file; This may not be as up to date as the DOWNLOADS

To initialize the V40 processors integrated peripherals you write command bytes to specific IO ports. Ports 0xFFF0-0xFFFF .

INITIALIZE_70208:

;0XFFFF RES


MOV DX, 0XFFFE ;OPCN - INT SELECT

MOV AL, 0X00 ;BIT 3 = INT1, BIT 2 = INT2, BIT 1-0 = 10

OUT DX, AL


MOV DX, 0XFFFD ;OPSEL - ENABLE PERIPHERAL

MOV AL, 0X06 ;ONLY ENABLE THE INTERRUPT CONTROLLER AND TIMER

OUT DX, AL ;


MOV DX, 0XFFFC ;OPHA - ON CHIP PERIPHERAL HIGH ADDRESS REGISTER

MOV AL, 0X00 ;ANY 256K BLOCK EXCEPT OVERLAP WITH RESGISTERS

OUT DX, AL


MOV DX, 0XFFFB ;DULA - DMA LOWER ADDRESS REGISTER

MOV AL, 0X00

OUT DX, AL


MOV DX, 0XFFFA ;IULA - 8259 LOWER ADDRESS REGISTER

MOV AL, 0X20

OUT DX, AL


MOV DX, 0XFFF9 ;TULA - 8254 LOWER ADDRESS REGISTER

MOV AL, 0X40

OUT DX, AL


MOV DX, 0XFFF8 ;SULA - SERIAL PORT LOWER ADDRESS REGISTER

MOV AL, 0XD0

OUT DX, AL


;0XFFF7 RES


MOV DX, 0XFFF6 ;WCY2 - WAIT

MOV AL, 0X0F ;Sets the number of wait cycles for DMA and refresh cycles

OUT DX, AL


MOV DX, 0XFFF5 ;WCY1 - WAIT

MOV AL, 0XFF ;BITS 7-6 = IO, 5-4 = UPPER MEM, 3-2 = MIDDLE MEM, 1-0 LOWER MEM

;00 NO WAIT, 11 LONGEST WAIT

OUT DX, AL


MOV DX, 0XFFF4 ;WMB - MEMORY BOUNDARIES

MOV AL, 0X71 ;BITS 6-4 LOWEST MEMORY, BITS 2-0 HIGHEST MEMORY, MIDDLE IS EVERYTHING ELSE

OUT DX, AL ;


;0XFFF3 RES


MOV DX, 0XFFF2 ;RFC - REFRESH CONTROL

MOV AL, 0X00 ;NO REFRESH

OUT DX, AL


;0XFFF1 RES


MOV DX, 0XFFF0 ;TCKS - TIMER PIN SELECTION

MOV AL, 0X14 ;1=PIN, 0=INTERNAL, BITS 1-0 PRESCALE DIV FOR INTERNAL

OUT DX, AL


RET

Initialize the Interrupt Controller.


INITIALIZE_8259:

PUSH AX


MOV AL, 0X13 ;ICW1

OUT 0X20, AL

MOV AL, 0X08 ;ICW2

OUT 0X21, AL

MOV AL, 0X09 ;ICW4

OUT 0X21, AL


MOV AL, 0XBC ;OCW1

OUT 0X21, AL ;UNMASK IRQ0, IRQ1, IRQ6

POP AX

RET


Initialize the System timer and speaker.

INITIALIZE_8253:


PUSH AX

PUSH CX


MOV AL, 0X36 ;00110110b

;CHANNEL 0

;WRITE LOW BYTE THEN HIGH BYTE

;MODE 3

;16 BIT COUNTER

OUT 0X43, AL ;CONTROL REG


MOV CX, 0XFFFF ;COUNT


MOV AL, CL ;WRITE LOW BYTE OF COUNT

OUT 0X40, AL ;PORT 0X40

;INTERNAL FLIP-FLOP INC

MOV AL, CH ;WRITE HIGH BYTE OF COUNT

OUT 0X40, AL ;PORT 040


;;;;;;;;;;;

;TEST TONE

;;;;;;;;;;;

MOV AL, 0X03 ;ENABLE SPK AND TIMMER 2 'GO'

OUT 0X61, AL ;PORT 0X61 CONTROL PORT

MOV AL, 0XB6

OUT 0X43, AL

MOV AL, 0X00

OUT 0X42, AL

MOV AL, 0X05

OUT 0X42, AL


POP CX

POP AX


RET

Initialize the USB host for the Hard Drive

INITIALIZE_CH376S_0XE0:


MOV AL, 0X05 ;COMMAND RESET

OUT 0XE4, AL ;OUT COMMAND PORT

CALL WAIT_8

MOV AL, 0X15 ;SET_USB_MODE

OUT 0XE4, AL ;OUT COMMAND PORT

MOV AL, 0X06 ;MODE 0X06

OUT 0XE0, AL ;OUT DATA PORT

CALL WAIT_16 ;DELAY TO GIVE IT TIME

MOV AL, 0X31 ;DISK_MOUNT

OUT 0XE4, AL ;OUT COMMAND PORT

CALL WAIT_16 ;DELAY TO GIVE IT TIME

CALL LOAD_BOOT_RECORD ;LOADS MBR CHECKS FOR BOOTABLE

;THEN LOADS VOLUME BOOT RECORD CHECKS FOR BOOTABLE

;DISK GEOMETRY IS USED IN OTHER 0X13 OPERATIONS


RET ;RETURN


Initialize the Keyboard Controller

INITIALIZE_W32C42P_0X60:

MOV AL, 0X60 ;WRITE COMMAND BYTE TO KEYBOARD CONTROLLER

OUT 0X64, AL ;OUT COMMAND PORT

MOV AL, 0X21 ;PC MODE, ENABLE INTERRUPT

OUT 0X60, AL ;OUT DATA PORT

RET ;RET

Initialize the 8255 for the LCD screen

INITIALIZE_8255_LCD:

PUSH AX

MOV AH, 0X00 ;LCD SET VIDEO MODE

INT 0X10

POP AX

RET

BIOS Interrupts:

This code is in no way complete or fully functional. Use at your own risk. This is the bare minimum need to run my system.

Interrupt 0x08

INT08: ;Reserved

PUSH AX ;STORE AX

PUSH BX ;STORE BX

PUSH DS ;STORE DS

MOV AX, 0X0040 ;BIOS DATA AREA

MOV DS, AX ;SET DATA SEGMENT

MOV BX, 0X006C ;SET BX TO TICK COUNTER

INC WORD [BX] ;INC LOWER WORD TICK BY ONE

CMP WORD [BX], 0X0000 ;CMP TO 0 TO SEE IF ROLLED OVER

JNZ .END_INT08 ;IF NOT END

ADD BX, 0X0002 ;ADD 2 TO BX FOR NEXT WORD

INC WORD [BX] ;INC UPPER WORD

.END_INT08: ;END LABEL

POP DS ;RESTORE DS

POP BX ;RESTORE BX

POP AX ;RESTORE AX


MOV AL, 0x20

OUT 0x20, AL

IRET ;RETURN FROM INTERRUPT

Interrupt 0x09 - This only writes the scan code to the screen.


INT09:

PUSH AX ;STORE AX

IN AL, 0X60 ;GET SCANCODE

CALL WIRTE_AL_INT10_E

JMP .END

.END:

MOV AL, 0x20

OUT 0x20, AL

POP AX

IRET


Interrupt 0x10 - This is for the LCD Screen through a 8255

INT10:

CMP AH, 0X00

JZ .VIDEO_MODE

CMP AH, 0X0E

JZ .TELOTYPE

IRET


.LCD_PORT_DATA:

DW 0X0440

.LCD_PORT_CONTROL:

DW 0X0441

.PORT_8255_MODE:

DW 0X0443


.VIDEO_MODE:

PUSH DS

PUSH AX

PUSH DX

;Setup 8255

MOV AL, 0XC0 ;MODE 2 PORT B OUTPUT

MOV DX, [CS:.PORT_8255_MODE]

OUT DX, AL ;WRITE TO 8255 COMMAND PORT

MOV AL, 0X31 ;b00110001

MOV DX, [CS:.LCD_PORT_CONTROL]

OUT DX, AL ;PORT B IS THE LCD CONTROL PORT

;SETUP LCD

MOV AL, 0X06 ;Increment cursor (shift cursor to right)

CALL .WRITE_COMMAND

MOV AL, 0X0F ;Display on, cursor blinking

CALL .WRITE_COMMAND

MOV AL, 0X38 ;2 lines and 5×7 matrix

CALL .WRITE_COMMAND

MOV AL, 0X01 ;Clear display screen

CALL .WRITE_COMMAND


MOV AX, 0X0040 ;BIOS DATA AREA SEGMENT

MOV DS, AX ;SET DS

MOV WORD [0X0050], 0X0000 ;WRITE ZERO TO COL, ROW


POP DX

POP AX

POP DS

IRET


.TELOTYPE:

PUSH CX

PUSH BX

PUSH AX

PUSH DS

CMP AL, 0X0D

JE .ENTER

CMP AL, 0X0A

JE .LINE_FEED

CMP AL, 0X08

JE .BACKSPACE


CALL .WRITE_CHAR


MOV AX, 0X0040 ;BIOS DATA AREA

MOV DS, AX ;SET DS

MOV AL, [0X0050] ;GET CURRENT COL

INC AL ;INC COL

CMP AL, 20 ;CHECK FOR END

JB .NOT_END_COLS ;JMP NOT END


MOV BYTE [0X0050], 0X00 ;IF END WRITE ZERO

MOV AL, [0X0051] ;GET CURRENT ROW

INC AL ;INC ROW

CMP AL, 4 ;CHECK FOR END

JB .NOT_END_ROWS ;JMP NOT END


CALL .SCROLL_UP


JMP .END_WRITE_CHAR


.NOT_END_COLS:

MOV [0X0050], AL

JMP .END_WRITE_CHAR


.NOT_END_ROWS:

MOV [0X0051], AL

JMP .END_WRITE_CHAR


.ROW_INDEX:

DB 0X80, 0XC0, 0X94, 0XD4


;;;;;;;;;;;WORK ING PROGRESS

.BACKSPACE:

MOV AX, 0X0040 ;BIOS DATA AREA

MOV DS, AX ;SET DS

MOV AL, [0X0050] ;GET CURRENT COL

CMP AL, 0X00 ;CHECK FOR COL 0, DONT WANT TO BACKSPACE PAST

JE .END_WRITE_CHAR ;JMP TO END IF 0

DEC AL ;DEC COL

MOV [0X0050], AL ;SAVE COL

MOV BX, .ROW_INDEX ;THIS MOVES THE CURSOR

ADD BL, [0X0051] ;

MOV AL, [CS:BX] ;

ADD AL, [0X0050] ;

CALL .WRITE_COMMAND ;


MOV AL, 0X20

CALL .WRITE_CHAR

JMP .END_WRITE_CHAR


.LINE_FEED:

MOV AX, 0X0040 ;BIOS DATA AREA

MOV DS, AX ;SET DS

MOV AL, [0X0051] ;GET CURRENT ROW

INC AL ;INC ROW

CMP AL, 4 ;CHECK FOR END

JB .NOT_END_ROWS ;JMP NOT END

CALL .SCROLL_UP

JMP .END_WRITE_CHAR


.ENTER:

MOV AX, 0X0040 ;BIOS DATA AREA

MOV DS, AX ;SET DS

MOV BYTE [0X0050], 0X00 ;GET CURRENT COL

JMP .END_WRITE_CHAR


.END_WRITE_CHAR:


MOV BX, .ROW_INDEX ;THIS MOVES THE CURSOR

ADD BL, [0X0051]

MOV AL, [CS:BX]

ADD AL, [0X0050]

CALL .WRITE_COMMAND


POP DS

POP AX

POP BX

POP CX

IRET


.READ_CHAR:

PUSH CX

PUSH DX

MOV DX, [CS:.LCD_PORT_CONTROL]

MOV AL, 0X37

OUT DX, AL

MOV AL, 0X36

OUT DX, AL

MOV AL, 0X27

OUT DX, AL

MOV AL, 0X37

OUT DX, AL

MOV CX, 0X0030

DB 0XE2, 0xFE ;LOOP HOLD FOR A BIT'

MOV DX, [CS:.LCD_PORT_DATA]

IN AL, DX

POP DX

POP CX


RET


.WRITE_CHAR:

PUSH CX

PUSH AX

PUSH DX

MOV DX, [CS:.LCD_PORT_DATA]

OUT DX, AL

MOV DX, [CS:.LCD_PORT_CONTROL]

MOV AL, 0X15

OUT DX, AL

MOV AL, 0X14

OUT DX, AL

MOV CX, 0X0030

DB 0XE2, 0xFE ;LOOP HOLD FOR A BIT'

MOV AL, 0X35

OUT DX, AL

POP DX

POP AX

POP CX

RET


.SCROLL_UP:

PUSH AX

PUSH CX

PUSH SI

PUSH DI

PUSH DS


MOV SI, 0XC0

MOV DI, 0X80

CALL .SCROLL_UP_SUB


MOV SI, 0X94

MOV DI, 0XC0

CALL .SCROLL_UP_SUB


MOV SI, 0XD4

MOV DI, 0X94

CALL .SCROLL_UP_SUB


MOV AL, 0XD4

CALL .WRITE_COMMAND

MOV CX, 20

MOV AL, 0X20

.LINE4:

CALL .WRITE_CHAR

LOOP .LINE4

JMP .END_SCROLL


.SCROLL_UP_SUB:

MOV CX, 20

.LOOP_LINES_1_3:

MOV AX, SI

CALL .WRITE_COMMAND

CALL .READ_CHAR

PUSH AX

MOV AX, DI

CALL .WRITE_COMMAND

POP AX

CALL .WRITE_CHAR

INC SI,

INC DI

LOOP .LOOP_LINES_1_3

RET


.END_SCROLL:

POP DS

POP DI

POP SI

POP CX

POP AX

RET



.WRITE_COMMAND:

PUSH CX

PUSH AX

PUSH DX

MOV DX, [CS:.LCD_PORT_DATA]

OUT DX, AL

MOV DX, [CS:.LCD_PORT_CONTROL]

MOV AL, 0X11

OUT DX, AL

MOV AL, 0X10

OUT DX, AL

MOV CX, 0x0500

DB 0XE2, 0xFE ;LOOP HOLD FOR A BIT'

MOV AL, 0X31

OUT DX, AL

POP DX

POP AX

POP CX


RET

Interrupt 0x11

INT11: ;Equipment Check

PUSH DS ;STORE DS

PUSH BX ;STORE BX

MOV AX, 0X0040 ;BIOS DATA AREA

MOV DS, AX ;SET DATA SEGMENT

MOV BX, 0X0010 ;OFFSET 0X10 EQUIPMENT LIST

MOV AX, WORD [BX] ;STORE EQUPMENT LIST AX

POP BX ;RESTORE BX

POP DS ;RESTORE DS

IRET ;RETRUN

Interrupt 0x12

INT12: ;Memory

PUSH DS ;STORE DS

PUSH BX ;STORE BX

MOV AX, 0X0040 ;BIOS DATA AREA

MOV DS, AX ;SET DATA SEGMENT

MOV BX, 0X0013 ;OFFSET 0X13 FOR MEMORY SIZE

MOV AX, WORD [BX] ;STORE MEMORY SIZE AX

POP BX ;RESTORE BX

POP DS ;RESTORE DS

IRET ;RETRUN

Interrupt 0x13 - This is for the CH376S usb drive. Currently Read Only

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;INT 0X0E HARDWARE DISK INTERRUPTS

;SUPPORTED STATUS

;0X15 = DISK CONNECTED

; DISPLAYS MESSAGE

;

;0X16 = DISK DISCONNECTED

; DISPLAYS MESSAGE

;

;ALL OTHER STATUS ARE IGNORED AT THIS TIME

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

INT0E:

PUSH AX ;STORE REGISTERS

PUSH BX ;

PUSH CX ;

PUSH DX ;

PUSH DS ;

MOV AL, 0X22 ;GET_STATUS

OUT 0XE4, AL ;OUT COMMAND PORT

IN AL, 0XE0 ;READ IN STATUS DATA PORT

CMP AL, 0X15 ;CHECK FOR USB CONNECT

JE .USB_INT_CONNECT ;IF CONNECT

CMP AL, 0X16 ;CHECK FOR USB DISCONNECT

JE .USB_INT_DISCONNECT ;IF DISCONNECT


.END_INT0E: ;END LABEL

POP DS ;RESTORE REGISTERS

POP DX ;

POP CX ;

POP BX ;

MOV AL, 0x20 ;8259 END INT COMMAND

OUT 0x20, AL ;OUT PORT 0X20

POP AX ;GET AX

IRET ;RETURN

.USB_INT_DISCONNECT:

MOV AX, CS ;GET CS

MOV DS, AX ;SET DS TO CS

MOV AH, 0X0E ;FOR TELOTYPE

MOV CX, .END_USB_INT_DISCONNECT_MESSAGE - .USB_INT_DISCONNECT_MESSAGE

MOV BX, .USB_INT_DISCONNECT_MESSAGE

.LOOP_USB_INT_DISCONNECT:

MOV AL, [BX] ;GET BYTE

INT 0X10 ;PRINT TO SCREEN

INC BX ;INC BX

LOOP .LOOP_USB_INT_DISCONNECT ;LOOP UNTIL DONE

CALL WAIT_32 ;GIVE IT TIME

JMP .END_INT0E


.USB_INT_DISCONNECT_MESSAGE:

DB 0X0D, 0X0A, 'DRIVE DISCONNECTED', 0X0D, 0X0A

.END_USB_INT_DISCONNECT_MESSAGE:

.USB_INT_CONNECT: ;0X15

MOV AX, CS ;GET CS

MOV DS, AX ;SET DS TO CS

MOV AH, 0X0E ;FOR TELOTYPE

MOV CX, .END_USB_INT_CONNECT_MESSAGE - .USB_INT_CONNECT_MESSAGE

MOV BX, .USB_INT_CONNECT_MESSAGE

.LOOP_USB_INT_CONNECT:

MOV AL, [BX] ;GET BYTE

INT 0X10 ;PRINT TO SCREEN

INC BX ;INC BX

LOOP .LOOP_USB_INT_CONNECT ;LOOP UNTIL DONE

CALL WAIT_16 ;DELAY TO GIVE IT TIME

MOV AL, 0X31 ;DISK_MOUNT

OUT 0XE4, AL ;OUT COMMAND PORT

CALL WAIT_16 ;DELAY TO GIVE IT TIME

CALL LOAD_BOOT_RECORD ;LOADS MBR CHECKS FOR BOOTABLE

JMP .END_INT0E


.USB_INT_CONNECT_MESSAGE:

DB 0X0D, 0X0A, 'DRIVE CONNECTED', 0X0D, 0X0A

.END_USB_INT_CONNECT_MESSAGE:

JMP .END_INT0E ;JUMP TO END



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;INT 0X13 SOFTWARE DISK INTERRUPTS

;DONT FORGET HARDWARE INTERRUPTS ARE DISABLED WHEN SOFTWARE INTERRUPTS ARE CALLED

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

INT13:

CMP DL, 0X80 ;CHECK FOR DISK NUMBER BEING REQUESTED

JE .START_INT13 ;JMP IF 0X80 C:

JNE .NOT_A_DRIVE ;JMP IF NOT C: NOT A DRIVE IN THE SYSTEM


.START_INT13:

CMP AH, 0X00

JE .RESET_DISK_SYSTEM ;RESET DISK

CMP AH, 0X01

JE .GET_STATUS_LAST_OPERATION ;GET STATUS OF LAST OPERATION

CMP AH, 0X02

JE .DISK_READ ;READ DISK CHS

CMP AH, 0X03

;JE .WRITE_DISK ;WRITE DISK CHS

CMP AH, 0X08

JE .PARAMETERS ;GET DISK PARAMETERS

CMP AH, 0X15

JE .GET_DISK_TYPE ;GET DISK TYPE

;FUNCTION NOT FOUND

MOV AH, 0X01 ;INVALID FUNCTION IN AH

STC ;SET CARRY FLAG

JMP .INT13_END_WITH_CARRY_FLAG

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;RESET DISK

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

.RESET_DISK_SYSTEM:

MOV AH, 0X00 ;STATUS 0X00 SUCCESSFULL

CLC ;CLEAR CARRY FLAG SUCCESFUL

JMP .INT13_END_WITH_CARRY_FLAG


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;STATUS OF LAST OPERATION

;THIS PROABLY WILL NEED WORK

;THE CH376 ERROR STATUS NUMBERS DO NOT MATCH PC COMPATABLE NUMBERS

;STATUS 0X14 IS SUCCESS AND INTERPRETED TO RETURN 0X00

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

.GET_STATUS_LAST_OPERATION:

MOV AL, 0X22 ;GET_STATUS OF INT

OUT 0XE4, AL ;OUT COMMAND PORT

IN AL, 0XE0 ;READ IN STATUS DATA PORT

CMP AL, 0X14 ;CHECK FOR USB_INT_SUCCESS

JNE .STATUS_DISK_ERROR;IF USB_INT_SUCCESS

MOV AH, 0X00 ;STATUS 0X00 SUCCESSFULL

CLC ;CLEAR CARRY FLAG SUCCESFUL

JMP .INT13_END_WITH_CARRY_FLAG

.STATUS_DISK_ERROR:

MOV AH, AL ;STATUS CODE

STC ;SET CARRY FLAG

JMP .INT13_END_WITH_CARRY_FLAG


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;READ DISK SECTOR

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;LBA = (C × HPC + H) × SPT + (S − 1)

;MAX NUMBERS C = 0X3FF, H = 0XFF, S = 0X3F

;AH = 02h

;AL = number of sectors to read (must be nonzero)

;CH = low eight bits of cylinder number

;CL = sector number 1-63 (bits 0-5)

;high two bits of cylinder (bits 6-7, hard disk only)

;DH = head number

;DL = drive number (bit 7 set for hard disk)

;ES:BX -> data buffer

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

.DISK_READ:

PUSH BX ;

PUSH CX ;STORE REGISTERS

PUSH DX ;

PUSH DS ;

PUSH ES ;

PUSH AX ;STORE AX / AL NUMBER OF SECTORS

PUSH AX ;STORE AX / AL NUMBER OF SECTORS

PUSH CX ;STORE CX / SECTOR NUMBER

PUSH DX ;STORE DX / DH HEAD NUMBER

MOV AX, 0XF400 ;DRIVE DATA AREA

MOV DS, AX ;SET DS TO 0XF400

MOV AL, CH ;GET LOWER CYLINDER NUMBER

SHR CL, 0X01 ;SHIFT RIGHT 6 TIMES FOR UPPER 2 BITS CYLINDER

SHR CL, 0X01 ;

SHR CL, 0X01 ;

SHR CL, 0X01 ;

SHR CL, 0X01 ;

SHR CL, 0X01 ;

MOV AH, CL ;AX HOLDS CYLINDER NUMBER ;

MOV CX, [0X021A] ;NUMBER OF HEADS / SIDES (HPC)

MUL CX ;AX = C X HPC

POP CX ;GET HEAD NUMBER

MOV CL, CH ;MOV HEAD NUMBER

MOV CH, 0X00 ;CLEAR CH

ADD AX, CX ;ADD IN HEAD (C X HPC + H)

MOV CX, [0X0218] ;SECTORS PER TRACK

MUL CX ;DX:AX (C X HPC + H) X SPT

POP CX ;GET SECTOR NUMBER

AND CX, 0X003F ;CLEAR OUT CYLINDER

DEC CX ;(S - 1)

ADD AX, CX ;LBA = (C × HPC + H) × SPT + (S − 1)

ADC DX, 0X00 ;IF THERE IS A CARRY POSIBLE I DONT KNOW

;DX:AX = LBA

PUSH DX ;STORE LBA UPPER

PUSH AX ;STORE LBA LOWER

MOV AL, 0X54 ;DISK_READ

OUT 0XE4, AL ;OUT COMMAND PORT

POP AX ;GET LOWER LBA

OUT 0XE0, AL ;OUT DATA PORT

MOV AL, AH ;NEXT BYTE

OUT 0XE0, AL ;OUT DATA PORT

POP AX ;GET UPPER LBA

OUT 0XE0, AL ;OUT DATA PORT

MOV AL, AH ;NEXT BYTE

OUT 0XE0, AL ;OUT DATA PORT

POP AX ;GET NUMBER OF SECTORS

OUT 0XE0, AL ;OUT DATA PORT


.READ_SECTOR:

MOV CX, 0X00FF ;DELAY

DB 0XE2, 0XFE ;LOOP BACK

MOV AL, 0X22 ;GET_STATUS

OUT 0XE4, AL ;OUT COMMAND PORT

IN AL, 0XE0 ;READ IN STATUS DATA PORT

CMP AL, 0X14 ;CHECK FOR USB_INT_SUCCESS COMPLETED READING

JE .READ_DISK_SUCCESS;IF USB_INT_SUCCESS

CMP AL, 0X1D ;COMPARE TO USB_INT_DISK_READ

JNE .NOT_1D ;IF NOT USB_INT_DISK_READ

MOV AL, 0X27 ;RD_USB_DATA0

OUT 0XE4, AL ;OUT COMMAND PORT

IN AL, 0XE0 ;READ NUMBER OF BYTES FROM DATA PORT

MOV AH, 0X00 ;CLEAR AH

MOV CX, AX ;SET CX TO NUMBER OF BYTES

.READ_IN_LOOP: ;LOOP LABLE

IN AL, 0XE0 ;READ BYTE

MOV [ES:BX], AL ;STORE BYTE

INC BX ;INC BX

LOOP .READ_IN_LOOP ;LOOP UNTIL DONE

MOV AL, 0X55 ;DISK_RD_GO READ NEXT 64 BYTES

OUT 0XE4, AL ;OUT COMMAND PORT

JMP .READ_SECTOR ;LOOP UNTIL DONE


.NOT_1D:

CALL WIRTE_AL_INT10_E ;PRINTS ERROR NUMBER TO SCREEN

MOV AX, CS ;GET CS

MOV DS, AX ;SET DS TO CS

MOV AH, 0X0E ;FOR TELOTYPE

MOV CX, .END_READ_ERROR_MESSAGE - .READ_ERROR_MESSAGE

MOV BX, .READ_ERROR_MESSAGE

.LOOP_NOT_1D:

MOV AL, [BX] ;GET BYTE

INT 0X10 ;PRINT TO SCREEN

INC BX ;INC BX

LOOP .LOOP_NOT_1D ;LOOP UNTIL DONE

JMP .READ_DISK_ERROR


.READ_ERROR_MESSAGE:

DB 0X0D, 0X0A, 'USB READ ERR0R', 0X0D, 0X0A

.END_READ_ERROR_MESSAGE:


.READ_DISK_SUCCESS:

POP AX

POP ES

POP DS

POP DX

POP CX

POP BX

MOV AH, 0X00 ;STATUS 0X00 SUCCESSFULL

CLC ;CLEAR CARRY FLAG SUCCESFUL

JMP .INT13_END_WITH_CARRY_FLAG

.READ_DISK_ERROR:

POP ES

POP ES

POP DS

POP DX

POP CX

POP BX


MOV AH, AL ;STATUS CODE

STC ;SET CARRY FLAG

JMP .INT13_END_WITH_CARRY_FLAG



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;GET PARAMETERS 0X08

;RETURNS

;AH=STATUS 0X00 IS GOOD

;BL=DOES NOT APPLY

;CH=CYLINDERS

;CL=0-5 SECTORS PER TRACK 6-7 UPPER 2 BITS CYLINDER

;DH=NUMBER OF HEADS / SIDES -1

;DL=NUMBER OF DRIVES

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

.PARAMETERS:

PUSH AX ;STORE AX

PUSH BX ;STORE BX

PUSH DS ;STORE DS

MOV AX, 0XF400 ;DRIVE DATA AREA

MOV DS, AX ;SET DS TO 0XF400

MOV BX, 0X03FE ;INDEX OF VOLUME BOOT SIGNATURE

CMP WORD [BX], 0XAA55 ;TEST TO SEE IF PRESENT

JNE .PARAMETERS_NOT_P ;IF NOT THERE

MOV BX, 0X0213 ;INDEX 0XF400:0X0213 SMALL SECTOR COUNT

CMP WORD [BX], 0X0000 ;IF ZERO THEN IT IS A LARGER THAN 32MB

JE .LARGE_SECTOR_COUNT_PARAMETERS ;JMP TO LARGE DRIVE CODE

.SMALL_SECTOR_COUNT_PARAMETERS:

MOV DX, 0X0000 ;DX = 0

MOV AX, [0X213] ;GET SECTOR COUNT

JMP .CONTINUE_PARAMETERS

.LARGE_SECTOR_COUNT_PARAMETERS:

MOV DX, [0X0222] ;DX UPPER 2 BYTES SECTOR COUNT

MOV AX, [0X0220] ;AX LOWER 2 BYTES SECTOR COUNT

JMP .CONTINUE_PARAMETERS

.CONTINUE_PARAMETERS:

MOV CX, [0X0218] ;SECTORS PER TRACK

DIV CX ;DIV DX:AX / CX

MOV DX, 0X0000 ;CLEAR DX JUST IN CASE THERE SHOULD NOT BE A REMANDER

MOV CX, [0X021A] ;NUMBER OF HEADS / SIDES

DIV CX ;DIV DX:AX / CX

;NOW WE HAVE CYLINDERS

MOV CH, AL ;CH=0-7 CYLINDERS

SHL AH, 0X01 ;SHIFT LEFT 6 TIMES UPPER 2 BITS CYLINDER

SHL AH, 0X01 ;

SHL AH, 0X01 ;

SHL AH, 0X01 ;

SHL AH, 0X01 ;

SHL AH, 0X01 ;

MOV CL, [0X0218] ;SECTORS PER TRACK

AND CL, 0X3F ;CLEAR BITS 7-6

ADD CL, AH ;ADD IN 8-9 BITS CYLINDER

MOV DH, [0X021A] ;NUMBER OF HEADS / SIDES

DEC DH ;START 0 NOT 1

MOV DL, 0X01 ;NUMBER OF DRIVES

JMP .END_PARAMETERS


.END_PARAMETERS:

POP DS ;RESTORE DS

POP BX ;RESTORE BX

POP AX ;RESTORE AX

MOV AH, 0X00 ;STATUS 0X00 SUCCESSFULL

CLC ;CLEAR CARRY FLAG SUCCESFUL

JMP .INT13_END_WITH_CARRY_FLAG

.PARAMETERS_NOT_P:

POP DS ;RESTORE DS

POP BX ;RESTORE BX

POP AX ;RESTORE AX

MOV AH, 0X01 ;STATUS 0X00 SUCCESSFULL

STC ;SET CARRY FLAG

JMP .INT13_END_WITH_CARRY_FLAG


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;GET DISK TYPE 0X15

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

.GET_DISK_TYPE:

PUSH BX ;STORE BX

PUSH DS ;STORE DS

MOV AX, 0XF400 ;DRIVE DATA AREA

MOV DS, AX ;SET DS TO 0XF400

MOV BX, 0X03FE ;INDEX OF VOLUME BOOT SIGNATURE

CMP WORD [BX], 0XAA55 ;TEST TO SEE IF PRESENT

JNE .GET_DISK_TYPE_NOT_P ;IF NOT THERE

MOV BX, 0X0213 ;INDEX 0XF400:0X0213 SMALL SECTOR COUNT

CMP WORD [BX], 0X0000 ;IF ZERO THEN IT IS A LARGER THAN 32MB

JE .LARGE_SECTOR_COUNT ;JMP TO LARGE DRIVE CODE

.SMALL_SECTOR_COUNT:

MOV DX, [BX] ;CX:DX NUMBER OF SECTORS

MOV CX, 0X0000 ;SMALL SECTOR CX IS 0X0000

MOV AX, 0X0300 ;AH=0X03 FIXED DISK AL=RETURN 0X00

JMP .END_GET_DISK_TYPE ;END

.LARGE_SECTOR_COUNT:

MOV BX, 0X0220 ;INDEX 0XF400:0X0200 LARGE SECTOR COUNT

MOV DX, [BX] ;CX:DX NUMBER OF SECTORS

ADD BX, 0X02 ;INC BX 2

MOV CX, [BX] ;CX:DX NUMBER OF SECTORS

MOV AX, 0X0300 ;AH=0X03 FIXED DISK AL=RETURN 0X00

JMP .END_GET_DISK_TYPE ;END

.GET_DISK_TYPE_NOT_P:

MOV AX, 0X0000 ;AH=0X00 WHEN NOT PRESENT

JMP .END_GET_DISK_TYPE

.END_GET_DISK_TYPE:

POP DS ;RESTORE DS

POP BX ;RESTORE BX

CLC ;CLEAR CARRY FLAG SUCCESFUL

JMP .INT13_END_WITH_CARRY_FLAG



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;END INT 0X13 WITH UPDATED CARRY FLAG

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

.INT13_END_WITH_CARRY_FLAG: ;THIS IS HOW I RETURN THE CARRY FLAG

PUSH AX ;STORE AX

PUSHF ;STORE FLAGS

POP AX ;GET AX = FLAGS

PUSH BP ;STORE BP

MOV BP, SP ;Copy SP to BP for use as index

ADD BP, 0X08 ;offset 8

AND WORD [BP], 0XFFFE ;CLEAR CF = ZER0

AND AX, 0X0001 ;ONLY CF

OR WORD [BP], AX ;SET CF AX

POP BP ;RESTORE BASE POINTER

POP AX ;RESTORE AX

IRET ;RETRUN


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;WHEN REQUEST IS NOT A VALID DRIVE NUMBER

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

.NOT_A_DRIVE:

MOV AH, 0X01 ;STATUS 0X00 SUCCESSFULL

STC ;SET CARRY FLAG

JMP .INT13_END_WITH_CARRY_FLAG


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;THIS LOADS THE MBR TO 0XF400:0000

;LOADS THE VBR TO 0XF400:0200

;USED BY INT 0X13 FOR CHS->LBA CALC

;THE VBR HAS THE DRIVE GEOMETRY AT

;0XF400:0X0218 DW SPT

;0XF400:0X021A DW HPC

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


LOAD_BOOT_RECORD:

PUSHF ;STORE FLAGS

CLI ;

PUSH AX ;STORE AX

PUSH BX ;STORE BX

PUSH CX ;STORE CX

PUSH DS ;STORE DS

MOV AX, 0XF400 ;

MOV DS, AX ;SET DS 0XF400 UPPER RAM

MOV BX, 0X0000 ;SET BX 0 FOR INDEX

;READ MBR

MOV AL, 0X54 ;DISK_READ COMMAND

OUT 0XE4, AL ;OUT COMMAND PORT

MOV AL, 0X00 ;LBA 0X00000000

OUT 0XE0, AL ;OUT COMMAND PORT

OUT 0XE0, AL ;OUT COMMAND PORT

OUT 0XE0, AL ;OUT COMMAND PORT

OUT 0XE0, AL ;OUT COMMAND PORT

MOV AL, 0X01 ;READ ONE SECTOR

OUT 0XE0, AL ;OUT COMMAND PORT


.READ_MBR_SECTOR:

MOV CX, 0X00FF ;DELAY

DB 0XE2, 0XFE ;LOOP BACK

MOV AL, 0X22 ;GET_STATUS

OUT 0XE4, AL ;OUT COMMAND PORT

IN AL, 0XE0 ;READ IN STATUS DATA PORT

CMP AL, 0X14 ;CHECK FOR USB_INT_SUCCESS COMPLETED READING

JE .READ_MBR_SUCCESS;IF USB_INT_SUCCESS

CMP AL, 0X1D ;COMPARE TO USB_INT_DISK_READ

JNE .NOT_1D ;IF NOT USB_INT_DISK_READ

MOV AL, 0X27 ;RD_USB_DATA0

OUT 0XE4, AL ;OUT COMMAND PORT

IN AL, 0XE0 ;READ NUMBER OF BYTES FROM DATA PORT

MOV AH, 0X00 ;CLEAR AH

MOV CX, AX ;SET CX TO NUMBER OF BYTES

.READ_MBR_LOOP: ;LOOP LABLE

IN AL, 0XE0 ;READ BYTE

MOV [BX], AL ;WRITE BYTE TO DS:BX

INC BX ;INC INDEX

LOOP .READ_MBR_LOOP ;LOOP UNTIL DONE

MOV AL, 0X55 ;DISK_RD_GO READ NEXT 64 BYTES

OUT 0XE4, AL ;OUT COMMAND PORT

JMP .READ_MBR_SECTOR;LOOP UNTIL DONE


.NOT_1D:

CALL WIRTE_AL_INT10_E ;PRINTS ERROR NUMBER TO SCREEN

MOV AX, CS ;GET CS

MOV DS, AX ;SET DS TO CS

MOV AH, 0X0E ;FOR TELOTYPE

MOV CX, .END_READ_ERROR_MESSAGE - .READ_ERROR_MESSAGE

MOV BX, .READ_ERROR_MESSAGE

.LOOP_NOT_1D:

MOV AL, [BX] ;GET BYTE

INT 0X10 ;PRINT TO SCREEN

INC BX ;INC BX

LOOP .LOOP_NOT_1D ;LOOP UNTIL DONE

JMP .END_LOAD_BOOT_RECORD


.READ_ERROR_MESSAGE:

DB ' USB READ ERR0R', 0X0D, 0X0A

.END_READ_ERROR_MESSAGE:

.NOT_BOOTABLE_MBR:

MOV AX, CS ;GET CS

MOV DS, AX ;SET DS TO CS

MOV AH, 0X0E ;FOR TELOTYPE

MOV CX, .END_NOT_MBR_MESSAGE - .NOT_MBR_MESSAGE

MOV BX, .NOT_MBR_MESSAGE

.LOOP_NOT_MBR:

MOV AL, [BX] ;GET BYTE

INT 0X10 ;PRINT TO SCREEN

INC BX ;INC BX

LOOP .LOOP_NOT_MBR ;LOOP UNTIL DONE

JMP .END_LOAD_BOOT_RECORD


.NOT_MBR_MESSAGE:

DB 'NO BOOT SIGNATURE MBR', 0X0D, 0X0A

.END_NOT_MBR_MESSAGE:

.READ_MBR_SUCCESS:

MOV BX, 0X01FE ;END OF MBR DS STILL IS 0XF400

CMP WORD [BX], 0XAA55 ;BOOT SIGNATURE DS:BX

JNE .NOT_BOOTABLE_MBR ;IF BOOT SIGNATURE IS NOT THERE

CALL WAIT_16 ;DELAY NEEDED BEFORE READING THE NEXT SECTOR

MOV BX, 0X01BE ;FIRST PARTITION ENTRY

CMP BYTE [BX], 0X80 ;CHECK FOR BOOTABLE

JE .BOOT_FIRST_ENTRY ;

MOV BX, 0X01CE ;SECOND PARTITION ENTRY

CMP BYTE [BX], 0X80 ;CHECK FOR BOOTABLE

JE .BOOT_SECOND_ENTRY ;

MOV BX, 0X01DE ;THRID PARTITION ENTRY

CMP BYTE [BX], 0X80 ;CHECK FOR BOOTABLE

JE .BOOT_THIRD_ENTRY ;

MOV BX, 0X01EE ;FORTH PARTITION ENTRY

CMP BYTE [BX], 0X80 ;CHECK FOR BOOTABLE

JE .BOOT_FORTH_ENTRY ;

JMP .NO_BOOTABLE_PARTITION

.BOOT_FIRST_ENTRY:

MOV AL, 0X54 ;DISK_READ COMMAND

OUT 0XE4, AL ;OUT COMMAND PORT

MOV BX, 0X01C6 ;PARTITION LBA START LOCATION

MOV AL, [BX] ;GET BYTE

OUT 0XE0, AL ;OUT DATA PORT

INC BX ;NEXT BYTE

MOV AL, [BX] ;GET BYTE

OUT 0XE0, AL ;OUT DATA PORT

INC BX ;NEXT BYTE

MOV AL, [BX] ;GET BYTE

OUT 0XE0, AL ;OUT DATA PORT

INC BX ;NEXT BYTE

MOV AL, [BX] ;GET BYTE

OUT 0XE0, AL ;OUT DATA PORT

INC BX ;NEXT BYTE

MOV AL, 0X01 ;READ ONE SECTOR

OUT 0XE0, AL

MOV BX, 0X0200 ;SET BX 200 FOR INDEX

JMP .READ_VBR_SECTOR

.BOOT_SECOND_ENTRY:

MOV AL, 0X54 ;DISK_READ COMMAND

OUT 0XE4, AL ;OUT COMMAND PORT

MOV BX, 0X01D6 ;PARTITION LBA START LOCATION

MOV AL, [BX] ;GET BYTE

OUT 0XE0, AL ;OUT DATA PORT

INC BX ;NEXT BYTE

MOV AL, [BX] ;GET BYTE

OUT 0XE0, AL ;OUT DATA PORT

INC BX ;NEXT BYTE

MOV AL, [BX] ;GET BYTE

OUT 0XE0, AL ;OUT DATA PORT

INC BX ;NEXT BYTE

MOV AL, [BX] ;GET BYTE

OUT 0XE0, AL ;OUT DATA PORT

INC BX ;NEXT BYTE

MOV AL, 0X01 ;READ ONE SECTOR

OUT 0XE0, AL

MOV BX, 0X0200 ;SET BX 200 FOR INDEX

JMP .READ_VBR_SECTOR

.BOOT_THIRD_ENTRY:

MOV AL, 0X54 ;DISK_READ COMMAND

OUT 0XE4, AL ;OUT COMMAND PORT

MOV BX, 0X01E6 ;PARTITION LBA START LOCATION

MOV AL, [BX] ;GET BYTE

OUT 0XE0, AL ;OUT DATA PORT

INC BX ;NEXT BYTE

MOV AL, [BX] ;GET BYTE

OUT 0XE0, AL ;OUT DATA PORT

INC BX ;NEXT BYTE

MOV AL, [BX] ;GET BYTE

OUT 0XE0, AL ;OUT DATA PORT

INC BX ;NEXT BYTE

MOV AL, [BX] ;GET BYTE

OUT 0XE0, AL ;OUT DATA PORT

INC BX ;NEXT BYTE

MOV AL, 0X01 ;READ ONE SECTOR

OUT 0XE0, AL

MOV BX, 0X0200 ;SET BX 200 FOR INDEX

JMP .READ_VBR_SECTOR

.BOOT_FORTH_ENTRY:

MOV AL, 0X54 ;DISK_READ COMMAND

OUT 0XE4, AL ;OUT COMMAND PORT

MOV BX, 0X01F6 ;PARTITION LBA START LOCATION

MOV AL, [BX] ;GET BYTE

OUT 0XE0, AL ;OUT DATA PORT

INC BX ;NEXT BYTE

MOV AL, [BX] ;GET BYTE

OUT 0XE0, AL ;OUT DATA PORT

INC BX ;NEXT BYTE

MOV AL, [BX] ;GET BYTE

OUT 0XE0, AL ;OUT DATA PORT

INC BX ;NEXT BYTE

MOV AL, [BX] ;GET BYTE

OUT 0XE0, AL ;OUT DATA PORT

INC BX ;NEXT BYTE

MOV AL, 0X01 ;READ ONE SECTOR

OUT 0XE0, AL

MOV BX, 0X0200 ;SET BX 200 FOR INDEX

JMP .READ_VBR_SECTOR

.READ_VBR_SECTOR:

MOV CX, 0X00FF ;DELAY

DB 0XE2, 0XFE ;LOOP BACK

MOV AL, 0X22 ;GET_STATUS

OUT 0XE4, AL ;OUT COMMAND PORT

IN AL, 0XE0 ;READ IN STATUS DATA PORT

CMP AL, 0X14 ;CHECK FOR USB_INT_SUCCESS COMPLETED READING

JE .READ_VBR_SUCCESS;IF USB_INT_SUCCESS

CMP AL, 0X1D ;COMPARE TO USB_INT_DISK_READ

JNE .NOT_1D ;IF NOT USB_INT_DISK_READ

MOV AL, 0X27 ;RD_USB_DATA0

OUT 0XE4, AL ;OUT COMMAND PORT

IN AL, 0XE0 ;READ NUMBER OF BYTES FROM DATA PORT

MOV AH, 0X00 ;CLEAR AH

MOV CX, AX ;SET CX TO NUMBER OF BYTES

.READ_VBR_LOOP: ;LOOP LABLE

IN AL, 0XE0 ;READ BYTE

MOV [BX], AL ;WRITE BYTE TO DS:BX

INC BX ;INC INDEX


LOOP .READ_VBR_LOOP ;LOOP UNTIL DONE

MOV AL, 0X55 ;DISK_RD_GO READ NEXT 64 BYTES

OUT 0XE4, AL ;OUT COMMAND PORT

JMP .READ_VBR_SECTOR ;LOOP UNTIL DONE


.READ_VBR_SUCCESS:

MOV BX, 0X01FE ;END OF MBR

CMP WORD [BX], 0XAA55 ;BOOT SIGNATURE

JNE .NOT_BOOTABLE_VBR ;IF BOOT SIGNATURE IS NOT THERE

JMP .END_LOAD_BOOT_RECORD

.NOT_BOOTABLE_VBR:

MOV AX, CS ;GET CS

MOV DS, AX ;SET DS TO CS

MOV AH, 0X0E ;FOR TELOTYPE

MOV CX, .END_NOT_VBR_MESSAGE - .NOT_VBR_MESSAGE

MOV BX, .NOT_VBR_MESSAGE

.LOOP_NOT_VBR:

MOV AL, [BX] ;GET BYTE

INT 0X10 ;PRINT TO SCREEN

INC BX ;INC BX

LOOP .LOOP_NOT_VBR ;LOOP UNTIL DONE

JMP .END_LOAD_BOOT_RECORD


.NOT_VBR_MESSAGE:

DB 'NO BOOT SIGNATURE VBR', 0X0D, 0X0A

.END_NOT_VBR_MESSAGE:


.NO_BOOTABLE_PARTITION:

MOV AX, CS ;GET CS

MOV DS, AX ;SET DS TO CS

MOV AH, 0X0E ;FOR TELOTYPE

MOV CX, .END_NO_BOOTABLE_PARTITION_MESSAGE - .NO_BOOTABLE_PARTITION_MESSAGE

MOV BX, .NO_BOOTABLE_PARTITION_MESSAGE

.LOOP_NO_BOOT_PARTITION:

MOV AL, [BX] ;GET BYTE

INT 0X10 ;PRINT TO SCREEN

INC BX ;INC BX

LOOP .LOOP_NO_BOOT_PARTITION ;LOOP UNTIL DONE

JMP .END_LOAD_BOOT_RECORD


.NO_BOOTABLE_PARTITION_MESSAGE:

DB 'NO BOOT PARTITION FOUND', 0X0D, 0X0A

.END_NO_BOOTABLE_PARTITION_MESSAGE:


.END_LOAD_BOOT_RECORD:

POP DS ;RESTORE DS

POP CX ;RESTORE CX

POP BX ;RESTORE BX

POP AX ;RESTORE AX

POPF ;RESTORE FLAGS

RET ;RETURN NOT A INT

Interrupt 0x15

INT15: ;Cassette

MOV AL, 0X00 ;AL = 0X00

MOV AH, 0X86 ;NO CASSETTE PRESENT

STC ;NOT BIOS SUPPORTED

;THIS IS HOW I RETURN THE CARRY FLAG

PUSH AX ;STORE AX

PUSHF ;STORE FLAGS

POP AX ;GET AX = FLAGS

PUSH BP ;STORE BP

MOV BP, SP ;Copy SP to BP for use as index

ADD BP, 0X08 ;offset 8

AND WORD [BP], 0XFFFE ;CLEAR CF = ZER0

AND AX, 0X0001 ;ONLY CF

OR WORD [BP], AX ;SET CF AX

POP BP ;RESTORE BASE POINTER

POP AX ;RESTORE AX

IRET ;RETRUN

Interrupt 0x16

INT16:


CMP AH, 0X00 ;Check ah

JZ .WAIT_FOR_KEY ;ah=0

CMP AH, 0X01

JZ .CHECK_ZERO_FLAG ;ah=1

CMP AH, 0X02

JZ .GET_SHIFT_FLAGS ;ah=2

STI

IRET


.WAIT_FOR_KEY:

PUSH BX

PUSH DS

.WAIT_FOR_KEY_LOOP:

STI

MOV AX, 0X0040

MOV DS, AX

CLI

MOV BX, [0X001A] ;Tail

CMP BX, [0X001C] ;Head

JZ .WAIT_FOR_KEY_LOOP

MOV AX, [BX]

ADD BX, 0X0002 ;Mov bx forward through buffer

CMP BX, [0X0082] ;Check to see if at the end

JB .NOT_END_OF_BUFFER ;Jump over next step if not at the end

MOV BX, [0X0080] ;Set bx back to begining

.NOT_END_OF_BUFFER:

MOV [0X001A], BX

POP DS

POP BX

CMP AL, 0XE0

JZ .AL_0

STI

IRET

.AL_0:

MOV AL, 0x00

IRET


.CHECK_ZERO_FLAG:

PUSH BX

PUSH DS

MOV AX, 0X0040

MOV DS, AX


MOV BX, [0X001A] ;Tail

CMP BX, [0X001C] ;Head

MOV AX, [BX]

POP DS

POP BX

PUSH AX ;STORE AX

PUSHF ;STORE FLAGES

POP AX ;AX = FLAGS

PUSH BP ;STORE BP

MOV BP, SP ;Copy SP to BP for use as index

ADD BP, 0X08 ;offset 8

AND WORD [BP], 0XFFBF ;CLEAR ZF

AND AX, 0X0040 ;ONLY ZF

OR WORD [BP], AX ;SET ZF

POP BP ;RESTORE BASE POINTER

POP AX ;RESTORE AX

STI

IRET

.GET_SHIFT_FLAGS:

MOV AX, 0X0000 ;FOR NOW RETURNS NOTHING.

STI

IRET

Interrupt 0x19

INT19: ;Bootstrap

JMP 0XFFFF:0X0000 ;JUMPS TO BOOT CODE

Interrupt 0x1A

INT1A: ;Time of Day

PUSH DS

PUSH BX

MOV AX, 0X0040 ;BIOS DATA AREA

MOV DS, AX ;SET DS

MOV BX, 0X006C ;NUMBER OF CLICKS

MOV DX, WORD [BX] ;SET DX CLICKS

ADD BX, 0X0002

MOV CX, WORD [BX] ;0X006E

AND CX, 0x000F

MOV AX, 0X0000 ;

POP BX

POP DS

IRET