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