Rework BDOS to make use of BIOS entrypoints

This commit is contained in:
Nero 2019-10-29 11:08:11 +00:00
parent af61db5e40
commit a49e3b2610
12 changed files with 169 additions and 451 deletions

View File

@ -1,10 +1,10 @@
FLOPPY = 360
BDOS = 0xF000
BDOSIMG = bdos.bin
BDOSIMG = bdos/8086.bin
BIOS = 0xF800
BIOSIMG = bios8086.bin
BIOSIMG = bios/8086.bin
PROGRAMS = $(patsubst %.asm,%.com,$(wildcard com/*.asm))
DISTFILES = $(PROGRAMS)
@ -37,10 +37,6 @@ endif
default: fdimage.img
# BDOS image
bdos.bin: bdos/*.asm lib/*.asm
$(NASM) $(NASM_ARGS) -o $@ -I bdos bdos/main.asm
# Boot sectors
boot/%.bs: boot/%.asm
$(NASM) $(NASM_ARGS) -DFLOPPY=$(FLOPPY) -o $@ $<
@ -53,7 +49,10 @@ rom/%.rom: rom/%.asm
com/%.com: com/%.asm
$(NASM) $(NASM_ARGS) -o $@ $<
bios%.bin: bios/%.asm
bdos/%.bin: bdos/%.asm lib/*.asm
$(NASM) $(NASM_ARGS) -o $@ -I bdos $<
bios/%.bin: bios/%.asm
$(NASM) $(NASM_ARGS) -o $@ $<
fdimage.img: boot/fat.bs $(BDOSIMG) $(BIOSIMG) $(DISTFILES)

136
bdos/8086.asm Normal file
View File

@ -0,0 +1,136 @@
ORG BDOS
%include "bios/header.asm"
DISKBUF: EQU (BDOS-0x200) ; deblocking
STACK: EQU (DISKBUF) ; grows down
DEFDRV: EQU 4
FCB_DRV: EQU 0 ; BYTE 0=A: 1=B: 2=C: ...
FCB_NAM: EQU 1 ; 8 BYTES, space padded
FCB_EXT: EQU 9 ; 3 BYTES, space padded
FCB_TYP: EQU 12 ; 1 for regular file
FCB_BLK: EQU 13 ; current 128b block in sector
FCB_CLU: EQU 14 ; current sector
FCB_LFT: EQU 16 ; bytes left to read in current file
SYSCALL:
TEST CL, CL
JE SETUP
CMP CL, 1
JE GETC
CMP CL, 2
JE PUTC
CMP CL, 9
JE PUTS
CMP CL, 10
JE GETS
STC
RET
SETUP:
MOV SP, STACK
MOV BYTE [DEFDRV], 0x01
MOV CX, DISKBUF
CALL SETDMA
MOV DL, BYTE [DEFDRV]
ADD DL, '@'
CALL PUTC
MOV DL, '>'
CALL PUTC
MOV DX, 0x7F
MOV BYTE [0x7F], 0x2F
MOV BYTE [0x80], 2
CALL GETS
INT3
CLI
HALT:
HLT
JMP HALT
GETC:
CALL CONIN
TEST AL, AL
JZ GETC
PUSH DX
MOV DL, AL
CALL CONOUT
POP DX
ret
PUTC:
CALL CONOUT
RET
PUTS:
PUSH SI
MOV SI, DX
PUTS_L:
MOV DL, BYTE [SI]
CMP DL, '$'
JZ PUTS_E
CALL CONOUT
INC SI
JMP PUTS_L
PUTS_E:
POP SI
RET
; BX base ptr to buffer
; CH maximum BL
; CL minimum BL
GETS:
PUSH AX
PUSH CX
PUSH DX
PUSH BX
; BX is base pointer
MOV BX, DX
; CL is maximum, CH is current position
MOV CX, [BX]
XOR CH, CH
; BX starts at actual character area
ADD BX, 2
GETS_L:
; Read and maybe handle control chars
CALL GETC
CMP AL, 0x0D
JE GETS_E
CMP AL, 8
JE GETS_BS
; Store character
PUSH BX
ADD BL, CH
ADC BH, 0
MOV [BX], AL
POP BX
; Loop if we arent full yet
INC CH
CMP CH, CL
JC GETS_L
GETS_E:
; Append LF to CR
MOV DL, 0x0A
CALL PUTC
; Write back length data
SUB BX, 2
MOV [BX], CX
; Restore registers
POP BX
POP DX
POP CX
POP AX
ret
GETS_BS:
TEST CH, CH
JZ GETS_L
MOV DL, 0x20
CALL PUTC
MOV DL, 8
CALL PUTC
DEC CL
JMP GETS_L

View File

@ -1,56 +0,0 @@
console_hide_cursor:
push ax
push cx
mov ah, 1
mov cx, 0x1F1F
int 0x10
pop cx
pop ax
ret
console_show_cursor:
push ax
push cx
mov ah, 1
mov cx, 0x001F
int 0x10
pop cx
pop ax
ret
; Raw console i/o without echo
; IN DL character to output or FF
; OUT ZF if DL=FF: zero if character input
; AL if not ZF: ascii char, otherwise corrupt
console_io:
cmp dl, 0xFF
je .read
push ax
push bx
mov al, dl
mov ah, 0x0e
xor bx, bx
int 0x10
pop bx
pop ax
ret
.read:
call console_show_cursor
; if no character avail, exit with leaving
; cursor displayed
mov ah, 1
int 0x16
jz .end
pushf
; actually read character
xor ax, ax
int 0x16
call console_hide_cursor
; restore zero flag
popf
.end:
ret

View File

@ -1,168 +0,0 @@
disk_num: equ 0x40 ; BYTE drive number (A=0)
disk_heads: equ 0x41 ; BYTE number of heads/sides
disk_parm: equ 0x42 ; 11 BYTES for int 0x1E
disk_spt: equ 0x46 ; - BYTE
disk_parm_init:
push ax
push si
push di
push ds
; invalidate existing data
mov byte [disk_num], 0xFF
xor ax, ax
mov ds, ax
; if int 0x1E is already pointing to us,
; we have nothing to copy
mov di, disk_parm
lds si, [0x1E*4]
cmp si, di
je .correctparm
; copy bios table into our location
mov cx, 11
rep movsb
; make the interrupt vector point to our address
xor ax, ax
mov ds, ax
mov [0x1E*4], di
mov ax, cs
mov [0x1E*4+2], ax
.correctparm:
pop ds
pop di
pop si
pop ax
ret
disk_load_bpb:
mov ax, 0x0201
mov cx, 0x0001
xor dh, dh
mov bx, diskbuf
stc
int 0x13
jnc .end
; try a second time
mov ax, 0x0201
int 0x13
jnc .end
; try a third time
mov ax, 0x0201
int 0x13
.end:
ret
disk_select:
push ax
push cx
push dx
push bx
cmp byte [disk_num], dl
je .end
mov byte [disk_num], dl
call disk_load_bpb
jc .end
; Validate and apply sector size
mov ax, [diskbuf+fdc_ss]
; test ax, 0xF87F
; jnz .nobpd
call log2
sub al, 7
mov [disk_parm+3], al
; fetch sectors per track
mov al, [diskbuf+fdc_spt]
mov [disk_parm+4], al
; fetch number of sides/heads
mov ax, [diskbuf+fdc_nos]
mov [disk_heads], al
xor ah, ah
int 0x13
.end:
pop bx
pop dx
pop cx
pop ax
ret
; Setup CX, DX and BX for int 13h transfer
; IN BX ptr to 32-bit number
; OUT CL Sector number
; CH Cylinder number
; DL Drive number
; DH Head number
; BX Sector buffer
disk_prepare_chs:
mov ax, word [bx]
mov dx, word [bx+2]
xor bh, bh
mov bl, byte [disk_spt]
div word bx ; ax:temp = (lba / spt)
inc dx ; dx:sector = (lba % spt) + 1
mov cl, dl ; sector number
xor bx, bx
mov bl, byte [disk_heads]
xor dx, dx
div word bx ; ax:cylinder = (temp / nos)
; dx:head = (temp % nos)
mov ch, al ; cylinder number
mov dh, dl ; head number
mov dl, byte [disk_num]
mov bx, diskbuf
ret
; Read a sector into diskbuf
; IN BX ptr to DWORD giving sector number
disk_read:
push ax
push cx
push dx
push bx
call disk_prepare_chs
mov ax, 0x0201
int 0x13
pop bx
pop dx
pop cx
pop ax
ret
; Write a sector from diskbuf
; IN BX ptr to DWORD giving sector number
disk_write:
push ax
push cx
push dx
push bx
call disk_prepare_chs
mov ax, 0x0301
int 0x13
pop bx
pop dx
pop cx
pop ax
ret

View File

@ -27,7 +27,7 @@ print8:
add al, 0x07
.out:
mov dl, al
call console_output
call CONOUT
ret
dump:
@ -36,9 +36,9 @@ dump:
push dx
push bx
mov dl, 0x0A
call console_output
call CONOUT
mov dl, 0x0D
call console_output
call CONOUT
mov cx, 4
.loop_line:
push cx
@ -46,9 +46,9 @@ dump:
mov ax, bx
call print16
mov dl, ':'
call console_output
call CONOUT
mov dl, ' '
call console_output
call CONOUT
mov cx, 0x8
.loop_bin:
mov ax, [bx]
@ -57,7 +57,7 @@ dump:
inc bx
call print16
mov dl, ' '
call console_output
call CONOUT
loop .loop_bin
pop bx
mov cx, 0x10
@ -70,13 +70,13 @@ dump:
mov dl, [bx]
.print:
inc bx
call console_output
call CONOUT
loop .loop_ascii
pop cx
mov dl, 0x0A
call console_output
call CONOUT
mov dl, 0x0D
call console_output
call CONOUT
loop .loop_line
pop bx
pop dx

View File

@ -1,13 +0,0 @@
; Exec the cmdline at SI or 0x81
exec_chain:
mov si, 0x81
exec:
push bx
sub sp, 0x20
mov bx, sp
call fcb_parse
add sp, 0x20
pop bx
ret

View File

@ -1,8 +0,0 @@
; diskbuf needs to be defined
; User-accessible part of FCB (12 bytes)
fcb_drv: equ 0 ; 1 byte, 1=A: 2=B: 3=C:
fcb_fn: equ 1 ; 8 bytes
fcb_ext: equ 9 ; 3 bytes
fcb_type: equ 12 ; BYTE type identifier

View File

@ -1,62 +0,0 @@
cpu 8086
self: equ 0xF000
diskbuf: equ (self-0x200) ; deblocking
stack: equ (diskbuf) ; grows down
defdrv: equ 4
org self
jmp init
pad 3
self_offset:
db (self >> 8)
banner:
db "RDOS 2019-09", 0x0A, 0x0D, '$', 0
init:
mov sp, stack
mov byte [defdrv], 0x01
mov dx, banner
call print_string
call disk_parm_init
mov dx, 0x7F
mov byte [0x7F], 0x7F
mov byte [0x80], 2
call read_buffer
int3
cli
.halt:
hlt
jmp .halt
init_program:
db "HELLO.COM", 0
; helper function for idle loops
idle:
pushf
sti
hlt
popf
ret
%include "syscall.asm"
%include "con86.asm"
%include "exec.asm"
%include "fdc.asm"
%include "fcb.asm"
%include "fcbparse.asm"
%include "disk.asm"
%include "log2.asm"
%include "dump.asm"

View File

@ -1,31 +0,0 @@
; IN DS:SI offset of needle
; ES:DI offset to haystack table
; OUT ES:DI found offset in table
; ZF zero flag set if match
string_search_token:
push bp
push cx
.loop:
cmp BYTE [es:di], 0
je .fail
push si
push di
mov bp, di
xor ch, ch
mov cl, [es:di]
inc di
add bp, cx
inc bp
repe cmpsb
pop di
pop si
je .end
mov di, bp
jmp .loop
.fail:
stc
.end:
pop cx
pop cx
ret

View File

@ -1,96 +0,0 @@
cpm_syscall:
cmp cl, 0
je init
cmp cl, 1
jne console_input.chain
console_input.loop:
call idle
console_input:
push dx
mov dl, 0xFF
call console_io
pop dx
jz console_input.loop
test al, al
jz console_input.loop
push dx
mov dl, al
call console_output
pop dx
ret
.chain:
cmp cl, 2
jne console_output.chain
console_output:
cmp dl, 0xFF
je .end
call console_io
.end:
ret
.chain:
cmp cl, 9
jne print_string.chain
print_string:
push si
mov si, dx
.loop:
mov dl, BYTE [si]
cmp dl, '$'
jz .end
call console_output
inc si
jmp .loop
.end:
pop si
ret
.chain:
cmp cl, 10
jne read_buffer.chain
read_buffer:
push ax
push dx
push bx
push si
xor bx, bx
mov si, dx
.loop:
call console_input
cmp al, 0x0D
je .end
cmp al, 8
je .bs
mov [si+bx+2], al
inc bx
cmp bl, [si]
jc .loop
.end:
mov byte [si+bx+2], 0x0D
mov [si+1], bl
mov dl, 0x0A
call console_output
pop si
pop bx
pop dx
pop ax
ret
.bs:
test bx, bx
jz .loop
mov dl, 0x20
call console_output
mov dl, 8
call console_output
dec bx
jmp .loop
.chain:
stc
ret

View File

@ -28,7 +28,7 @@ BOOT:
DB "BIOS", 0
WBOOT:
XOR AX, AX
XOR CX, CX
JMP BDOS
RET

17
bios/header.asm Normal file
View File

@ -0,0 +1,17 @@
; Labels for BIOS entry points
BOOT: EQU (BIOS+0)
WBOOT: EQU (BIOS+3)
CONST: EQU (BIOS+6)
CONIN: EQU (BIOS+9)
CONOUT: EQU (BIOS+12)
LIST: EQU (BIOS+15)
PUNCH: EQU (BIOS+18)
READER: EQU (BIOS+21)
HOME: EQU (BIOS+24)
SELDSK: EQU (BIOS+27)
SETTRK: EQU (BIOS+30)
SETSEC: EQU (BIOS+33)
SETDMA: EQU (BIOS+36)
READ: EQU (BIOS+39)
WRITE: EQU (BIOS+42)
LISTST: EQU (BIOS+45)