parent
30ae244ef1
commit
4847eb4d88
3
Makefile
3
Makefile
@ -6,6 +6,9 @@ cp437.bin: src/cp437.bmp scripts/bmp2font
|
|||||||
vga11.bin: src/vga11.asm cp437.bin
|
vga11.bin: src/vga11.asm cp437.bin
|
||||||
nasm -o $@ $<
|
nasm -o $@ $<
|
||||||
|
|
||||||
|
forth.bin: src/forth.asm
|
||||||
|
nasm -o $@ $<
|
||||||
|
|
||||||
scripts/%: src/scripts/%.c
|
scripts/%: src/scripts/%.c
|
||||||
mkdir -p scripts
|
mkdir -p scripts
|
||||||
gcc -o $@ $<
|
gcc -o $@ $<
|
||||||
|
234
bdos/8086.asm
Normal file
234
bdos/8086.asm
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
ORG BDOS
|
||||||
|
|
||||||
|
%include "hdr/bios.asm"
|
||||||
|
%include "hdr/fcb.asm"
|
||||||
|
%include "hdr/bpb.asm"
|
||||||
|
|
||||||
|
DISKBUF: EQU (BDOS-0x200) ; deblocking
|
||||||
|
DISKBPB: EQU (DISKBUF-21) ; BPB of the current driv
|
||||||
|
DISKDRV: EQU (DISKBPB-1) ; BYTE denoting drive of current fcb (1=A, ...)
|
||||||
|
|
||||||
|
PROGBX: EQU (DISKDRV-2)
|
||||||
|
|
||||||
|
STACK: EQU (PROGBX & 0xFFFE) ; even address, grows down
|
||||||
|
|
||||||
|
DEFDRV: EQU 4 ; default drive when opening a FCB (1=A, ...)
|
||||||
|
|
||||||
|
SYSCALL:
|
||||||
|
MOV [PROGBX], BX
|
||||||
|
XOR BH, BH
|
||||||
|
MOV BL, CL
|
||||||
|
ADD BX, BX
|
||||||
|
ADD BX, FUNCS
|
||||||
|
MOV BX, [BX]
|
||||||
|
PUSH BX
|
||||||
|
MOV BX, [PROGBX]
|
||||||
|
SYSRET:
|
||||||
|
RET
|
||||||
|
|
||||||
|
FUNCS:
|
||||||
|
DW SETUP,GETC,PUTC,SYSRET
|
||||||
|
DW SYSRET,SYSRET,SYSRET,SYSRET
|
||||||
|
DW SYSRET,PUTS,GETS,STATUS
|
||||||
|
DW SYSRET,DISKRST,SETDEFDSK,FCBOPEN
|
||||||
|
DW SYSRET,SYSRET,SYSRET,SYSRET
|
||||||
|
DW SYSRET,SYSRET,SYSRET,SYSRET
|
||||||
|
|
||||||
|
SETUP:
|
||||||
|
MOV SP, STACK
|
||||||
|
MOV BYTE [DEFDRV], 0x01
|
||||||
|
MOV CX, DISKBUF
|
||||||
|
CALL SETDMA
|
||||||
|
|
||||||
|
SUB SP, 0x20
|
||||||
|
MOV BX, SP
|
||||||
|
CALL FCBOPEN
|
||||||
|
|
||||||
|
CLI
|
||||||
|
HALT:
|
||||||
|
HLT
|
||||||
|
JMP HALT
|
||||||
|
|
||||||
|
GETC:
|
||||||
|
CALL CONIN
|
||||||
|
TEST AL, AL
|
||||||
|
JZ GETC
|
||||||
|
PUSH DX
|
||||||
|
MOV DL, AL
|
||||||
|
CALL CONOUT
|
||||||
|
POP DX
|
||||||
|
ret
|
||||||
|
|
||||||
|
PUTC:
|
||||||
|
JMP CONOUT
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
STATUS:
|
||||||
|
JMP CONST
|
||||||
|
|
||||||
|
DISKRST:
|
||||||
|
MOV BYTE [DISKDRV], 0xFF
|
||||||
|
RET
|
||||||
|
|
||||||
|
SETDEFDSK:
|
||||||
|
MOV BYTE [DEFDRV], DL
|
||||||
|
RET
|
||||||
|
|
||||||
|
FCBOPEN:
|
||||||
|
MOV CL, BYTE [BX]
|
||||||
|
TEST CL, CL
|
||||||
|
JNZ NODEFDRV
|
||||||
|
MOV CL, BYTE [DEFDRV]
|
||||||
|
MOV BYTE [BX], CL
|
||||||
|
NODEFDRV:
|
||||||
|
CALL LOADBPB
|
||||||
|
|
||||||
|
MOV CX, [DISKBPB+BPB_RDE]
|
||||||
|
|
||||||
|
CALL FATSIZE
|
||||||
|
ADD DX, WORD [DISKBPB+BPB_RSC]
|
||||||
|
CALL SETLSEC
|
||||||
|
CALL READ
|
||||||
|
|
||||||
|
MOV AX, [DISKBUF]
|
||||||
|
|
||||||
|
INT3
|
||||||
|
; TODO: search for file in rootdir
|
||||||
|
; TODO: init cluster number
|
||||||
|
RET
|
||||||
|
|
||||||
|
; Set logical sector number
|
||||||
|
; IN DX sector number
|
||||||
|
SETLSEC:
|
||||||
|
PUSH AX
|
||||||
|
PUSH CX
|
||||||
|
PUSH DX
|
||||||
|
XOR AX, AX
|
||||||
|
XCHG AX, DX
|
||||||
|
DIV WORD [DISKBPB+BPB_SPT]
|
||||||
|
MOV CX, AX
|
||||||
|
CALL SETTRK
|
||||||
|
MOV CX, DX
|
||||||
|
INC CX
|
||||||
|
CALL SETSEC
|
||||||
|
POP DX
|
||||||
|
POP CX
|
||||||
|
POP AX
|
||||||
|
RET
|
||||||
|
|
||||||
|
; OUT DX number of sectors by all FATs
|
||||||
|
FATSIZE:
|
||||||
|
PUSH AX
|
||||||
|
MOV DL, BYTE [DISKBPB+BPB_FN]
|
||||||
|
MOV AL, BYTE [DISKBPB+BPB_SF]
|
||||||
|
MUL DL
|
||||||
|
XCHG AX, DX
|
||||||
|
POP AX
|
||||||
|
RET:
|
||||||
|
RET
|
||||||
|
|
||||||
|
; IN CL drive num, 1=A, 2=B, 3=C
|
||||||
|
LOADBPB:
|
||||||
|
CMP BYTE [DISKDRV], CL
|
||||||
|
JE RET
|
||||||
|
|
||||||
|
PUSH CX
|
||||||
|
DEC CL
|
||||||
|
CALL SELDSK
|
||||||
|
; first track
|
||||||
|
MOV CX, 0
|
||||||
|
CALL SETTRK
|
||||||
|
; first sector
|
||||||
|
MOV CX, 1
|
||||||
|
CALL SETSEC
|
||||||
|
; into default diskbuf
|
||||||
|
MOV CX, DISKBUF
|
||||||
|
CALL SETDMA
|
||||||
|
POP CX
|
||||||
|
|
||||||
|
CALL READ
|
||||||
|
JC DISKRST
|
||||||
|
|
||||||
|
; copy BPB
|
||||||
|
PUSH CX
|
||||||
|
PUSH SI
|
||||||
|
PUSH DI
|
||||||
|
MOV CX, 21
|
||||||
|
MOV SI, DISKBUF+0x0B
|
||||||
|
MOV DI, DISKBPB
|
||||||
|
REP MOVSB
|
||||||
|
POP DI
|
||||||
|
POP SI
|
||||||
|
POP CX
|
||||||
|
|
||||||
|
; store drive number
|
||||||
|
MOV BYTE [DISKDRV], CL
|
||||||
|
RET
|
85
bdos/dump.asm
Normal file
85
bdos/dump.asm
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
; print a word
|
||||||
|
; in: ax
|
||||||
|
print16:
|
||||||
|
xchg ah,al
|
||||||
|
call print8
|
||||||
|
xchg ah,al
|
||||||
|
|
||||||
|
; print a byte
|
||||||
|
; in: al
|
||||||
|
print8:
|
||||||
|
push ax ; avoid destroying ah
|
||||||
|
push bx
|
||||||
|
xor bx, bx
|
||||||
|
aam 16 ; high nibble moved into ah, low nibble into al
|
||||||
|
add ax, 0x3030
|
||||||
|
push ax
|
||||||
|
xchg al, ah
|
||||||
|
call .nib
|
||||||
|
pop ax
|
||||||
|
call .nib
|
||||||
|
pop bx
|
||||||
|
pop ax
|
||||||
|
ret
|
||||||
|
.nib:
|
||||||
|
cmp al, 0x3a
|
||||||
|
jl .out
|
||||||
|
add al, 0x07
|
||||||
|
.out:
|
||||||
|
mov dl, al
|
||||||
|
call CONOUT
|
||||||
|
ret
|
||||||
|
|
||||||
|
dump:
|
||||||
|
push ax
|
||||||
|
push cx
|
||||||
|
push dx
|
||||||
|
push bx
|
||||||
|
mov dl, 0x0A
|
||||||
|
call CONOUT
|
||||||
|
mov dl, 0x0D
|
||||||
|
call CONOUT
|
||||||
|
mov cx, 4
|
||||||
|
.loop_line:
|
||||||
|
push cx
|
||||||
|
push bx
|
||||||
|
mov ax, bx
|
||||||
|
call print16
|
||||||
|
mov dl, ':'
|
||||||
|
call CONOUT
|
||||||
|
mov dl, ' '
|
||||||
|
call CONOUT
|
||||||
|
mov cx, 0x8
|
||||||
|
.loop_bin:
|
||||||
|
mov ax, [bx]
|
||||||
|
xchg al, ah
|
||||||
|
inc bx
|
||||||
|
inc bx
|
||||||
|
call print16
|
||||||
|
mov dl, ' '
|
||||||
|
call CONOUT
|
||||||
|
loop .loop_bin
|
||||||
|
pop bx
|
||||||
|
mov cx, 0x10
|
||||||
|
.loop_ascii:
|
||||||
|
mov dl, '.'
|
||||||
|
cmp byte [bx], 0x20
|
||||||
|
jc .print
|
||||||
|
cmp byte [bx], 0x80
|
||||||
|
jnc .print
|
||||||
|
mov dl, [bx]
|
||||||
|
.print:
|
||||||
|
inc bx
|
||||||
|
call CONOUT
|
||||||
|
loop .loop_ascii
|
||||||
|
pop cx
|
||||||
|
mov dl, 0x0A
|
||||||
|
call CONOUT
|
||||||
|
mov dl, 0x0D
|
||||||
|
call CONOUT
|
||||||
|
loop .loop_line
|
||||||
|
pop bx
|
||||||
|
pop dx
|
||||||
|
pop cx
|
||||||
|
pop ax
|
||||||
|
ret
|
218
bios/8086.asm
Normal file
218
bios/8086.asm
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
ORG BIOS
|
||||||
|
CPU 8086
|
||||||
|
|
||||||
|
DISKCX: EQU 0x8
|
||||||
|
DISKDX: EQU 0xA
|
||||||
|
DISKBX: EQU 0xC
|
||||||
|
|
||||||
|
JMP NEAR BOOT
|
||||||
|
JMP NEAR WBOOT
|
||||||
|
JMP NEAR CONST
|
||||||
|
JMP NEAR CONIN
|
||||||
|
JMP NEAR CONOUT
|
||||||
|
JMP NEAR LIST
|
||||||
|
JMP NEAR PUNCH
|
||||||
|
JMP NEAR READER
|
||||||
|
JMP NEAR HOME
|
||||||
|
JMP NEAR SELDSK
|
||||||
|
JMP NEAR SETTRK
|
||||||
|
JMP NEAR SETSEC
|
||||||
|
JMP NEAR SETDMA
|
||||||
|
JMP NEAR READ
|
||||||
|
JMP NEAR WRITE
|
||||||
|
JMP NEAR LISTST
|
||||||
|
|
||||||
|
BOOT:
|
||||||
|
MOV AL, 0x86
|
||||||
|
CALL MSG
|
||||||
|
DB "BIOS", 0
|
||||||
|
|
||||||
|
WBOOT:
|
||||||
|
XOR CX, CX
|
||||||
|
JMP BDOS
|
||||||
|
RET
|
||||||
|
|
||||||
|
; CHAR I/O
|
||||||
|
CONST:
|
||||||
|
MOV AH, 1
|
||||||
|
INT 0x16
|
||||||
|
JZ .END
|
||||||
|
MOV AL, 0xFF
|
||||||
|
RET
|
||||||
|
.END:
|
||||||
|
XOR AL, AL
|
||||||
|
RET
|
||||||
|
|
||||||
|
CONIN:
|
||||||
|
XOR AX, AX
|
||||||
|
INT 0x16
|
||||||
|
TEST AL, AL
|
||||||
|
JZ CONIN
|
||||||
|
RET
|
||||||
|
|
||||||
|
MSG:
|
||||||
|
POP SI
|
||||||
|
.LOOP:
|
||||||
|
MOV DL, BYTE [SI]
|
||||||
|
INC SI
|
||||||
|
TEST DL, DL
|
||||||
|
JZ .END
|
||||||
|
CALL CONOUT
|
||||||
|
JMP .LOOP
|
||||||
|
.END:
|
||||||
|
MOV DL, 0x20
|
||||||
|
CALL CONOUT
|
||||||
|
CALL PRINTAL
|
||||||
|
MOV DL, 0x0A
|
||||||
|
CALL CONOUT
|
||||||
|
MOV DL, 0x0D
|
||||||
|
CALL CONOUT
|
||||||
|
PUSH SI
|
||||||
|
RET
|
||||||
|
|
||||||
|
PRINTAL:
|
||||||
|
PUSH AX
|
||||||
|
PUSH DX
|
||||||
|
AAM 16
|
||||||
|
MOV DL, AH
|
||||||
|
CALL PRINTNIB
|
||||||
|
MOV DL, AL
|
||||||
|
CALL PRINTNIB
|
||||||
|
POP DX
|
||||||
|
POP AX
|
||||||
|
RET
|
||||||
|
|
||||||
|
PRINTNIB:
|
||||||
|
ADD DL, 0x30
|
||||||
|
CMP DL, 0x3a
|
||||||
|
JL CONOUT
|
||||||
|
ADD DL, 0x07
|
||||||
|
|
||||||
|
CONOUT:
|
||||||
|
PUSH AX
|
||||||
|
PUSH BX
|
||||||
|
MOV AH, 0x0E
|
||||||
|
MOV AL, DL
|
||||||
|
XOR BX, BX
|
||||||
|
INT 0x10
|
||||||
|
POP BX
|
||||||
|
POP AX
|
||||||
|
RET
|
||||||
|
|
||||||
|
LIST:
|
||||||
|
PUSH DX
|
||||||
|
XOR AH, AH
|
||||||
|
MOV AL, DL
|
||||||
|
INT 0x17
|
||||||
|
POP DX
|
||||||
|
RET
|
||||||
|
|
||||||
|
LISTST:
|
||||||
|
STC
|
||||||
|
RET
|
||||||
|
|
||||||
|
PUNCH:
|
||||||
|
STC
|
||||||
|
RET
|
||||||
|
|
||||||
|
READER:
|
||||||
|
STC
|
||||||
|
RET
|
||||||
|
|
||||||
|
; DISK I/O
|
||||||
|
HOME:
|
||||||
|
MOV WORD [DISKCX], 0x0001
|
||||||
|
MOV BYTE [DISKDX+1], 0x00
|
||||||
|
RET
|
||||||
|
|
||||||
|
SELDSK:
|
||||||
|
MOV BYTE [DISKDX], CL
|
||||||
|
XOR BX, BX
|
||||||
|
RET
|
||||||
|
|
||||||
|
SETTRK:
|
||||||
|
PUSH CX
|
||||||
|
PUSH DX
|
||||||
|
|
||||||
|
MOV DX, CX
|
||||||
|
; CH for headnum, CL for SAL
|
||||||
|
MOV CX, 0x0006
|
||||||
|
|
||||||
|
; Take off LSB as head number
|
||||||
|
XOR CH, CH
|
||||||
|
RCR DX, 1
|
||||||
|
RCL CH, 1
|
||||||
|
MOV BYTE [DISKDX+1], CH
|
||||||
|
|
||||||
|
; DX is sector number now
|
||||||
|
; Shift into format for int13
|
||||||
|
; DX ------9876543210
|
||||||
|
SAL DX, CL
|
||||||
|
; DX 9876543210------
|
||||||
|
ROL DX, 1
|
||||||
|
ROL DX, 1
|
||||||
|
; DX 76543210------98
|
||||||
|
SAL DL, CL
|
||||||
|
; DX 7654321098------
|
||||||
|
AND WORD [DISKCX], 0x003F
|
||||||
|
OR WORD [DISKCX], DX
|
||||||
|
|
||||||
|
POP DX
|
||||||
|
POP CX
|
||||||
|
RET
|
||||||
|
|
||||||
|
SETSEC:
|
||||||
|
AND WORD [DISKCX], 0xFFC0
|
||||||
|
OR BYTE [DISKCX], CL
|
||||||
|
RET
|
||||||
|
|
||||||
|
SETDMA:
|
||||||
|
MOV WORD [DISKBX], CX
|
||||||
|
RET
|
||||||
|
|
||||||
|
READ:
|
||||||
|
PUSH CX
|
||||||
|
PUSH DX
|
||||||
|
PUSH BX
|
||||||
|
|
||||||
|
MOV AX, 0x0201
|
||||||
|
MOV CX, [DISKCX]
|
||||||
|
MOV DX, [DISKDX]
|
||||||
|
MOV BX, [DISKBX]
|
||||||
|
INT 0x13
|
||||||
|
XCHG AH, AL
|
||||||
|
|
||||||
|
POP BX
|
||||||
|
POP DX
|
||||||
|
POP CX
|
||||||
|
|
||||||
|
JC DISKERR
|
||||||
|
RET
|
||||||
|
|
||||||
|
WRITE:
|
||||||
|
PUSH CX
|
||||||
|
PUSH DX
|
||||||
|
PUSH BX
|
||||||
|
|
||||||
|
MOV AX, 0x0301
|
||||||
|
MOV CX, [DISKCX]
|
||||||
|
MOV DX, [DISKDX]
|
||||||
|
MOV BX, [DISKBX]
|
||||||
|
INT 0x13
|
||||||
|
XCHG AH, AL
|
||||||
|
|
||||||
|
POP BX
|
||||||
|
POP DX
|
||||||
|
POP CX
|
||||||
|
|
||||||
|
JC DISKERR
|
||||||
|
RET
|
||||||
|
|
||||||
|
DISKERR:
|
||||||
|
PUSHF
|
||||||
|
PUSH SI
|
||||||
|
CALL MSG
|
||||||
|
DB "DISKERR", 0
|
||||||
|
POP SI
|
||||||
|
POPF
|
||||||
|
RET
|
241
boot/fat.asm
Normal file
241
boot/fat.asm
Normal file
@ -0,0 +1,241 @@
|
|||||||
|
; Memory layout:
|
||||||
|
%define segment 0x00100
|
||||||
|
|
||||||
|
%define self (0x7C00-(segment<<4)) ; 1 sector
|
||||||
|
%define fattab (self+0x200) ; variable size
|
||||||
|
%define rootdir 0x00100 ; variable size
|
||||||
|
%define prog 0x0F000 ; 4K at the end for OS
|
||||||
|
|
||||||
|
org self
|
||||||
|
|
||||||
|
jmp short init
|
||||||
|
|
||||||
|
cluster_offset:
|
||||||
|
dw 0
|
||||||
|
|
||||||
|
times (0x0B - ($-$$)) db 0
|
||||||
|
|
||||||
|
fdc:
|
||||||
|
.ss:
|
||||||
|
dw 0x200 ; sector size
|
||||||
|
.sc:
|
||||||
|
db 2 ; sectors per cluster
|
||||||
|
.rsc:
|
||||||
|
dw 1 ; reserved sector count
|
||||||
|
.fn:
|
||||||
|
db 2 ; number of file allocation tables
|
||||||
|
.rde:
|
||||||
|
dw 0x70 ; number of root directory entries
|
||||||
|
.ts:
|
||||||
|
dw 720 ; total number of sectors
|
||||||
|
.mi: ; medium identifier
|
||||||
|
db 0xFD ; 5.25-inch Double sided, 40 tracks per side, 9 sectors per track (360 KB)
|
||||||
|
.sf: ; sectors per fat
|
||||||
|
dw 2
|
||||||
|
.spt:
|
||||||
|
dw 9 ; sectors per track
|
||||||
|
.nos:
|
||||||
|
dw 2 ; number of sides (heads)
|
||||||
|
.po:
|
||||||
|
dd 0 ; partition offset (in LBA blocks)
|
||||||
|
.lrgts:
|
||||||
|
dd 0
|
||||||
|
.drv:
|
||||||
|
db 0 ; drive number
|
||||||
|
db 0
|
||||||
|
db 0x29 ; efdc signature
|
||||||
|
.vid:
|
||||||
|
dd 0 ; volume id
|
||||||
|
.vlabel:
|
||||||
|
db "2B"
|
||||||
|
times (54 - ($-$$)) db " "
|
||||||
|
.fstype:
|
||||||
|
db "FAT12"
|
||||||
|
times (62 - ($-$$)) db " "
|
||||||
|
|
||||||
|
; mformat keeps writing until here
|
||||||
|
; if we place init earlier, code gets overwritten
|
||||||
|
times (62 - ($-$$)) nop
|
||||||
|
|
||||||
|
init:
|
||||||
|
cli
|
||||||
|
jmp segment:main
|
||||||
|
|
||||||
|
main:
|
||||||
|
; Stack grows down from 64k
|
||||||
|
mov ax, cs
|
||||||
|
mov ss, ax
|
||||||
|
mov sp, prog
|
||||||
|
mov ds, ax
|
||||||
|
mov es, ax
|
||||||
|
|
||||||
|
mov [fdc.drv], dl ; save drive number in fd
|
||||||
|
sti
|
||||||
|
|
||||||
|
; load fat table into memory
|
||||||
|
mov ax, [fdc.rsc]
|
||||||
|
mov cx, [fdc.sf]
|
||||||
|
xor dx, dx
|
||||||
|
mov bx, fattab
|
||||||
|
call load_sectors
|
||||||
|
|
||||||
|
; calculate length of rootdir
|
||||||
|
mov ax, [fdc.rde]
|
||||||
|
mov cl, 4
|
||||||
|
shr ax, cl ; 32 bytes per entry
|
||||||
|
mov cx, ax
|
||||||
|
|
||||||
|
; load root dir
|
||||||
|
xor dx, dx
|
||||||
|
mov ax, [fdc.sf]
|
||||||
|
mul byte [fdc.fn]
|
||||||
|
add ax, [fdc.rsc]
|
||||||
|
mov bx, rootdir
|
||||||
|
call load_sectors
|
||||||
|
|
||||||
|
; remember where we left off
|
||||||
|
; clusters start after rootdir
|
||||||
|
mov [cluster_offset], ax
|
||||||
|
|
||||||
|
; Load kernel
|
||||||
|
mov bx, prog
|
||||||
|
mov ax, kernel_name
|
||||||
|
call load_file
|
||||||
|
mov bp, 0x3332
|
||||||
|
jc error
|
||||||
|
|
||||||
|
mov dl, [fdc.drv]
|
||||||
|
|
||||||
|
; jump into kernel
|
||||||
|
jmp segment:prog
|
||||||
|
|
||||||
|
; Load a file into memory
|
||||||
|
; IN AX pointer to 8.3 filename
|
||||||
|
; ES:BX pointer to target area
|
||||||
|
; OUT CF flag set if error
|
||||||
|
; DI file size in bytes (<64K)
|
||||||
|
load_file:
|
||||||
|
mov si, rootdir
|
||||||
|
mov cx, [fdc.rde]
|
||||||
|
.search:
|
||||||
|
push cx
|
||||||
|
push si
|
||||||
|
mov di, ax
|
||||||
|
mov cx, 11
|
||||||
|
repe cmpsb
|
||||||
|
pop si
|
||||||
|
pop cx
|
||||||
|
je .read
|
||||||
|
add si, 0x20
|
||||||
|
loop .search
|
||||||
|
xor di, di
|
||||||
|
stc
|
||||||
|
ret
|
||||||
|
.read:
|
||||||
|
mov ax, [si+0x1A]
|
||||||
|
mov di, [si+0x1C]
|
||||||
|
jmp read_clusters
|
||||||
|
|
||||||
|
; Read the file given by cluster number
|
||||||
|
; into the target program area
|
||||||
|
; in ax cluster number
|
||||||
|
read_clusters:
|
||||||
|
; read cluster into area for target file
|
||||||
|
push ax
|
||||||
|
sub ax, 2
|
||||||
|
mul BYTE [fdc.sc]
|
||||||
|
add ax, [cluster_offset]
|
||||||
|
xor dx, dx
|
||||||
|
mov cx, [fdc.sc]
|
||||||
|
xor ch, ch
|
||||||
|
call load_sectors
|
||||||
|
pop ax
|
||||||
|
|
||||||
|
; calculate index in FAT
|
||||||
|
mov si, ax
|
||||||
|
shr si, 1
|
||||||
|
add si, ax
|
||||||
|
add si, fattab
|
||||||
|
|
||||||
|
; load entry from FAT, truncate to 12 bit
|
||||||
|
mov dx, [si]
|
||||||
|
test ax, 1
|
||||||
|
jz .noshift
|
||||||
|
mov cl, 4
|
||||||
|
shr dx, 4
|
||||||
|
.noshift:
|
||||||
|
mov ax, dx
|
||||||
|
|
||||||
|
and ax, 0x0FFF
|
||||||
|
cmp ax, 0x0FF8
|
||||||
|
jc read_clusters
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
; Read sectors from disk
|
||||||
|
; Does not return on error
|
||||||
|
; ax and bx will be incremented, cx decremented
|
||||||
|
; in dx:ax sector number
|
||||||
|
; es:bx buffer
|
||||||
|
; cx number of sectors to read
|
||||||
|
; out dx:ax next sector to read
|
||||||
|
; es:bx next free buffer
|
||||||
|
; cx zero
|
||||||
|
load_sectors:
|
||||||
|
; fail instantly if reading sectors > 16 bit
|
||||||
|
test dx, dx
|
||||||
|
mov bp, 0x3330
|
||||||
|
jnz error
|
||||||
|
|
||||||
|
.loop:
|
||||||
|
push ax
|
||||||
|
push cx
|
||||||
|
push dx
|
||||||
|
|
||||||
|
; add partition offset (required for HDD)
|
||||||
|
add ax, [fdc.po]
|
||||||
|
adc dx, [fdc.po+2]
|
||||||
|
|
||||||
|
; calculate CHS data
|
||||||
|
div word [cs:fdc.spt] ; ax:temp = (lba / spt)
|
||||||
|
inc dx ; dx:sector = (lba % spt) + 1
|
||||||
|
mov cl, dl ; sector number
|
||||||
|
xor dx, dx
|
||||||
|
div word [cs:fdc.nos] ; ax:cylinder = (tmp / heads)
|
||||||
|
; dx:head = (tmp % heads)
|
||||||
|
mov ch, al ; cylinder number
|
||||||
|
mov dh, dl ; head number
|
||||||
|
mov dl, [cs:fdc.drv] ; driver number
|
||||||
|
mov ax, 0x0201 ; ah=0x02 al=0x01
|
||||||
|
int 0x13
|
||||||
|
mov bp, 0x3331
|
||||||
|
jc error
|
||||||
|
|
||||||
|
pop dx
|
||||||
|
pop cx
|
||||||
|
pop ax
|
||||||
|
|
||||||
|
; count up for next sector
|
||||||
|
add bx, 0x0200
|
||||||
|
inc ax
|
||||||
|
|
||||||
|
loop .loop
|
||||||
|
ret
|
||||||
|
|
||||||
|
error:
|
||||||
|
mov ax, bp
|
||||||
|
mov ah, 0x0e
|
||||||
|
mov bx, 7
|
||||||
|
int 0x10
|
||||||
|
mov al, 0x21
|
||||||
|
int 0x10
|
||||||
|
xor ax, ax
|
||||||
|
int 0x16
|
||||||
|
int 0x19
|
||||||
|
|
||||||
|
kernel_name:
|
||||||
|
db "BDOS BIN"
|
||||||
|
|
||||||
|
times (0x1FE - ($-$$)) db 0
|
||||||
|
|
||||||
|
dw 0xAA55
|
136
boot/mbr.asm
Normal file
136
boot/mbr.asm
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
; Memory layout:
|
||||||
|
%define self 0x00600 ; 1 sector
|
||||||
|
%define prog 0x07C00 ; 1 sector
|
||||||
|
|
||||||
|
; FDC fields in VBR
|
||||||
|
%define spt (prog + 0x18)
|
||||||
|
%define nos (prog + 0x1A)
|
||||||
|
%define po (prog + 0x1C)
|
||||||
|
|
||||||
|
org self
|
||||||
|
cpu 8086
|
||||||
|
|
||||||
|
init:
|
||||||
|
cli
|
||||||
|
|
||||||
|
; Stack grows down from PSP + 64k
|
||||||
|
xor ax, ax
|
||||||
|
mov ss, ax
|
||||||
|
mov sp, ax
|
||||||
|
|
||||||
|
push dx
|
||||||
|
|
||||||
|
; Relocate from [prog] to [self]
|
||||||
|
mov ds, ax
|
||||||
|
mov es, ax
|
||||||
|
mov si, prog
|
||||||
|
mov di, self
|
||||||
|
mov cx, 0x100
|
||||||
|
rep movsw
|
||||||
|
|
||||||
|
jmp 0:main
|
||||||
|
|
||||||
|
main:
|
||||||
|
mov bp, 0x3335
|
||||||
|
mov si, part1
|
||||||
|
mov cx, 4
|
||||||
|
.loop:
|
||||||
|
test BYTE [si], 0x80
|
||||||
|
jnz loadpart
|
||||||
|
add si, 0x10
|
||||||
|
loop .loop
|
||||||
|
jmp error
|
||||||
|
|
||||||
|
loadpart:
|
||||||
|
; transfer starting address into DAP
|
||||||
|
push si
|
||||||
|
add si, 0x08
|
||||||
|
mov di, dap.blocknum
|
||||||
|
movsw
|
||||||
|
movsw
|
||||||
|
pop si
|
||||||
|
|
||||||
|
; load sector
|
||||||
|
push si
|
||||||
|
mov si, dap
|
||||||
|
mov bp, 0x3336
|
||||||
|
mov ah, 0x42
|
||||||
|
stc
|
||||||
|
int 0x13
|
||||||
|
jc error
|
||||||
|
pop si
|
||||||
|
|
||||||
|
cmp BYTE [si+4], 0x01
|
||||||
|
jne jump
|
||||||
|
|
||||||
|
adjust:
|
||||||
|
push dx
|
||||||
|
|
||||||
|
mov bp, 0x3337
|
||||||
|
mov ah, 0x08
|
||||||
|
stc
|
||||||
|
int 0x13
|
||||||
|
jc error
|
||||||
|
|
||||||
|
; update sectors per track
|
||||||
|
xor ax, ax
|
||||||
|
mov al, cl
|
||||||
|
mov [spt], ax
|
||||||
|
|
||||||
|
; update number of sides
|
||||||
|
xor ax, ax
|
||||||
|
mov al, dh
|
||||||
|
mov [nos], ax
|
||||||
|
|
||||||
|
; update partition offset
|
||||||
|
push si
|
||||||
|
add si, 0x08
|
||||||
|
mov di, po
|
||||||
|
movsw
|
||||||
|
movsw
|
||||||
|
pop si
|
||||||
|
|
||||||
|
pop dx
|
||||||
|
|
||||||
|
jump:
|
||||||
|
jmp 0:prog
|
||||||
|
|
||||||
|
error:
|
||||||
|
mov ax, bp
|
||||||
|
mov ah, 0x0e
|
||||||
|
mov bx, 7
|
||||||
|
int 0x10
|
||||||
|
mov al, 0x21
|
||||||
|
int 0x10
|
||||||
|
xor ax, ax
|
||||||
|
int 0x16
|
||||||
|
int 0x19
|
||||||
|
|
||||||
|
dap:
|
||||||
|
.size:
|
||||||
|
db 0
|
||||||
|
db 0
|
||||||
|
.count:
|
||||||
|
dw 1
|
||||||
|
.buffer:
|
||||||
|
dw prog
|
||||||
|
dw 0
|
||||||
|
.blocknum:
|
||||||
|
dq 0
|
||||||
|
|
||||||
|
times (0x1BE - ($-$$)) db 0
|
||||||
|
part1:
|
||||||
|
db 0x80
|
||||||
|
.chs_start:
|
||||||
|
db 0xFF, 0xFF, 0xFF
|
||||||
|
.type:
|
||||||
|
db 0x01
|
||||||
|
.chs_end:
|
||||||
|
db 0xFF, 0xFF, 0xFF
|
||||||
|
.begin:
|
||||||
|
dd 1
|
||||||
|
.end:
|
||||||
|
dd (FLOPPY * 2)
|
||||||
|
|
||||||
|
times (0x1FE - ($-$$)) db 0
|
||||||
|
dw 0xAA55
|
90
boot/serial.asm
Normal file
90
boot/serial.asm
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
org 0x7c00
|
||||||
|
|
||||||
|
xor ax, ax
|
||||||
|
mov ds, ax
|
||||||
|
mov es, ax
|
||||||
|
mov ss, ax
|
||||||
|
mov sp, 0x7c00
|
||||||
|
jmp 0:start
|
||||||
|
|
||||||
|
getc:
|
||||||
|
mov ah, 0x02
|
||||||
|
mov dx, 0x0000
|
||||||
|
int 0x14
|
||||||
|
test ah, 0x80
|
||||||
|
jnz getc
|
||||||
|
ret
|
||||||
|
|
||||||
|
putc:
|
||||||
|
mov ah, 0x01
|
||||||
|
mov dx, 0x0000
|
||||||
|
int 0x14
|
||||||
|
ret
|
||||||
|
|
||||||
|
init_port:
|
||||||
|
mov ah, 0x00
|
||||||
|
mov al, 0b11100011
|
||||||
|
mov dx, 0x0000
|
||||||
|
int 0x14
|
||||||
|
ret
|
||||||
|
|
||||||
|
dump:
|
||||||
|
mov si, 0x500
|
||||||
|
mov cx, di
|
||||||
|
sub cx, si
|
||||||
|
.loop:
|
||||||
|
lodsb
|
||||||
|
call print8
|
||||||
|
loop .loop
|
||||||
|
mov al, 0x0A
|
||||||
|
call putc
|
||||||
|
mov al, 0x0D
|
||||||
|
call putc
|
||||||
|
ret
|
||||||
|
|
||||||
|
line_reset:
|
||||||
|
cmp di, 0x500
|
||||||
|
je .reset
|
||||||
|
call line_process
|
||||||
|
.reset:
|
||||||
|
mov di, 0x500
|
||||||
|
xor bp, bp
|
||||||
|
jmp mainloop
|
||||||
|
|
||||||
|
line_process:
|
||||||
|
call dump
|
||||||
|
ret
|
||||||
|
|
||||||
|
start:
|
||||||
|
call init_port
|
||||||
|
mov di, 0x500
|
||||||
|
jmp line_reset
|
||||||
|
|
||||||
|
mainloop:
|
||||||
|
call getc
|
||||||
|
cmp al, ':'
|
||||||
|
je line_reset
|
||||||
|
cmp al, 0x20
|
||||||
|
jb line_reset
|
||||||
|
sub al, 0x30
|
||||||
|
cmp al, 9
|
||||||
|
jbe .noadjust
|
||||||
|
sub al, 7
|
||||||
|
.noadjust:
|
||||||
|
test bp, bp
|
||||||
|
jnz .secondnib
|
||||||
|
mov cl, 4
|
||||||
|
shl al, cl
|
||||||
|
mov [di], al
|
||||||
|
not bp
|
||||||
|
jmp mainloop
|
||||||
|
.secondnib:
|
||||||
|
or [di], al
|
||||||
|
inc di
|
||||||
|
not bp
|
||||||
|
jmp mainloop
|
||||||
|
|
||||||
|
%include "print.asm"
|
||||||
|
|
||||||
|
times 510-($-$$) db 0x00
|
||||||
|
db 0x55,0xaa
|
21
com/asm86.asm
Normal file
21
com/asm86.asm
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
org 0x100
|
||||||
|
|
||||||
|
jmp start
|
||||||
|
|
||||||
|
%include "fcbparse.asm"
|
||||||
|
|
||||||
|
fcb_asm:
|
||||||
|
times 36 db 0
|
||||||
|
|
||||||
|
fcb_bin:
|
||||||
|
times 36 db 0
|
||||||
|
|
||||||
|
fcb_lst:
|
||||||
|
times 36 db 0
|
||||||
|
|
||||||
|
start:
|
||||||
|
mov si, 0x81
|
||||||
|
mov bx, fcb_asm
|
||||||
|
mov ax, 0x1234
|
||||||
|
call fcb_parse
|
||||||
|
ret
|
17
com/hello.asm
Normal file
17
com/hello.asm
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
org 0x0100
|
||||||
|
|
||||||
|
main:
|
||||||
|
mov si, hello
|
||||||
|
.loop:
|
||||||
|
lodsb
|
||||||
|
test al, al
|
||||||
|
jz .ret
|
||||||
|
mov dl, al
|
||||||
|
mov cl, 0x02
|
||||||
|
call 5
|
||||||
|
jmp .loop
|
||||||
|
.ret:
|
||||||
|
ret
|
||||||
|
|
||||||
|
hello:
|
||||||
|
db "Hello!", 0x0A, 0x0D, 0
|
17
hdr/bios.asm
Normal file
17
hdr/bios.asm
Normal 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)
|
12
hdr/bpb.asm
Normal file
12
hdr/bpb.asm
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
; BPB from first sector on FAT fs, starting 0x0B
|
||||||
|
BPB_SS: EQU 0 ; WORD sector size
|
||||||
|
BPB_SC: EQU 2 ; BYTE sectors per cluster
|
||||||
|
BPB_RSC: EQU 3 ; WORD reserved sector count
|
||||||
|
BPB_FN: EQU 5 ; BYTE number of FATs
|
||||||
|
BPB_RDE: EQU 6 ; WORD number of root directory entries
|
||||||
|
BPB_TS: EQU 8 ; WORD total number of sectors
|
||||||
|
BPB_MI: EQU 10 ; BYTE medium identifier
|
||||||
|
BPB_SF: EQU 11 ; WORD sectors per FAT
|
||||||
|
BPB_SPT: EQU 13 ; WORD sectors per track
|
||||||
|
BPB_NOS: EQU 15 ; WORD number of sides/heads
|
||||||
|
BPB_PO: EQU 17 ; DWORD partition offset
|
10
hdr/fcb.asm
Normal file
10
hdr/fcb.asm
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
; File control block
|
||||||
|
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 ; BYTE FCB type
|
||||||
|
; TYP=1: 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
|
||||||
|
FCB_END: EQU 20 ; FCB length
|
65
lib/earlymcb.asm
Normal file
65
lib/earlymcb.asm
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
%define mcb_first 0x5F
|
||||||
|
|
||||||
|
; This alloc uses an MCB-like list always starting at a fixed offset.
|
||||||
|
; Boot components may use it to allocate space during early boot.
|
||||||
|
; The list ends with the most recently allocated arena at its end,
|
||||||
|
; contrary to how the MCBs work on DOS.
|
||||||
|
|
||||||
|
; Memory Layout:
|
||||||
|
; 0000 Interrupt table
|
||||||
|
; 0400 BIOS data area
|
||||||
|
; 05F0 16 bytes Arena header 1
|
||||||
|
; 0600 BX paragraphs Arena 1
|
||||||
|
; .... 16 bytes Arena header 2
|
||||||
|
; .... BX paragraphs Arena 2
|
||||||
|
; ...
|
||||||
|
; .... 16 bytes Arena header n
|
||||||
|
; .... BX paragraphs Arena n
|
||||||
|
; Unmanaged memory
|
||||||
|
|
||||||
|
; Take note that this mechanism works differently than under DOS -
|
||||||
|
; but this one is optimized for fast and small alloc.
|
||||||
|
|
||||||
|
; Typical usecases:
|
||||||
|
; - Diskette Parameter Table (See interrupt 1Eh)
|
||||||
|
; - Partition table
|
||||||
|
; - Boot sector relocations
|
||||||
|
; - Boot sector data (FAT table, rootdir)
|
||||||
|
|
||||||
|
; Allocate paragraphs in unmanaged memory
|
||||||
|
; IN BX requested memory in paragraphs
|
||||||
|
; OUT AX output segment
|
||||||
|
early_alloc:
|
||||||
|
push ds
|
||||||
|
push bx
|
||||||
|
push si
|
||||||
|
; si is used as zero register
|
||||||
|
; this allows the opcodes to use a byte as disp instead of word
|
||||||
|
xor si, si
|
||||||
|
mov ax, mcb_first
|
||||||
|
.next:
|
||||||
|
mov ds, ax
|
||||||
|
inc ax
|
||||||
|
; DS is seg of arena header
|
||||||
|
; AX is seg of arena
|
||||||
|
cmp BYTE [si], 0x4D
|
||||||
|
jne .here
|
||||||
|
add ax, WORD [si+3]
|
||||||
|
jmp .next
|
||||||
|
.here:
|
||||||
|
; mark as item
|
||||||
|
mov BYTE [si], 0x4D
|
||||||
|
; write segment length in paragraphs
|
||||||
|
mov WORD [si+3], bx
|
||||||
|
; if allocation is higher than CS, then we are in managed memory
|
||||||
|
; set ourself as owner then, otherwise use dummy value 8
|
||||||
|
mov bx, cs
|
||||||
|
cmp ax, bx ; CF = CS in unmanaged memory
|
||||||
|
jnc .setup_owner
|
||||||
|
mov bx, 8
|
||||||
|
.setup_owner:
|
||||||
|
mov WORD [si+1], bx
|
||||||
|
pop si
|
||||||
|
pop bx
|
||||||
|
pop ds
|
||||||
|
ret
|
46
lib/fcbparse.asm
Normal file
46
lib/fcbparse.asm
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
; Parse ASCIIZ string into FCB
|
||||||
|
; IN SI ptr to filename
|
||||||
|
; BX ptr to FCB
|
||||||
|
fcb_parse:
|
||||||
|
push di
|
||||||
|
push ax
|
||||||
|
mov di, bx
|
||||||
|
xor ax, ax
|
||||||
|
stosb
|
||||||
|
.cleanout:
|
||||||
|
push di
|
||||||
|
mov cx, 0x0A
|
||||||
|
mov al, 0x20
|
||||||
|
rep stosb
|
||||||
|
pop di
|
||||||
|
.base_loop:
|
||||||
|
call .read
|
||||||
|
cmp al, 0x2E
|
||||||
|
je .ext_start
|
||||||
|
cmp al, 0x20
|
||||||
|
je .ret
|
||||||
|
stosb
|
||||||
|
jmp .base_loop
|
||||||
|
.ext_start:
|
||||||
|
mov di, bx
|
||||||
|
add di, 9
|
||||||
|
.ext_loop:
|
||||||
|
call .read
|
||||||
|
cmp al, 0x20
|
||||||
|
je .ret
|
||||||
|
stosb
|
||||||
|
jmp .ext_loop
|
||||||
|
.read:
|
||||||
|
lodsb
|
||||||
|
test al, al
|
||||||
|
jz .eret
|
||||||
|
cmp al, 0x0D
|
||||||
|
je .eret
|
||||||
|
ret
|
||||||
|
.eret:
|
||||||
|
dec si
|
||||||
|
pop ax
|
||||||
|
.ret:
|
||||||
|
pop ax
|
||||||
|
pop di
|
||||||
|
ret
|
14
lib/fdc.asm
Normal file
14
lib/fdc.asm
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
; FDC Descriptor / BIOS parameter block
|
||||||
|
fdc_ss: equ 0x0B ; WORD sector size
|
||||||
|
fdc_sc: equ 0x0D ; BYTE sectors per cluster
|
||||||
|
fdc_rsc: equ 0x0E ; WORD reserved sectors
|
||||||
|
fdc_fn: equ 0x10 ; BYTE FAT tables
|
||||||
|
fdc_rde: equ 0x11 ; WORD root directory entries
|
||||||
|
fdc_ts: equ 0x13 ; WORD total sector count
|
||||||
|
; 0 if >65535, use lrgts then
|
||||||
|
fdc_mi: equ 0x15 ; BYTE media descriptor byte
|
||||||
|
fdc_sf: equ 0x16 ; WORD sectors per FAT
|
||||||
|
fdc_spt: equ 0x18 ; WORD sectors per track
|
||||||
|
fdc_nos: equ 0x1A ; WORD sides/heads
|
||||||
|
fdc_po: equ 0x1C ; DWORD partition offset
|
||||||
|
fdc_lrgts: equ 0x20 ; DWORD large sector count
|
15
lib/log2.asm
Normal file
15
lib/log2.asm
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
; Calculate dual logarithm (int)
|
||||||
|
; IN AX number
|
||||||
|
; OUT AX dual logarithm
|
||||||
|
log2:
|
||||||
|
push cx
|
||||||
|
mov cx, 15
|
||||||
|
.loop:
|
||||||
|
rcl ax, 1
|
||||||
|
jc .ret
|
||||||
|
loop .loop
|
||||||
|
.ret:
|
||||||
|
cmc
|
||||||
|
mov ax, cx
|
||||||
|
pop cx
|
||||||
|
ret
|
124
lib/nasmcomp.asm
Normal file
124
lib/nasmcomp.asm
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
; Pseudo-Instruction: fill bytes until offset
|
||||||
|
%macro pad 1.nolist
|
||||||
|
times (%1 - ($-$$)) nop
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
; REGISTERS
|
||||||
|
%define a al
|
||||||
|
%define b ch
|
||||||
|
%define c cl
|
||||||
|
%define d dh
|
||||||
|
%define e dl
|
||||||
|
%define h bh
|
||||||
|
%define l bl
|
||||||
|
%define m byte [bx]
|
||||||
|
|
||||||
|
; REGISTER PAIRS
|
||||||
|
%define bc cx
|
||||||
|
%define de dx
|
||||||
|
%define hl bx
|
||||||
|
|
||||||
|
; INSTRUCTIONS
|
||||||
|
; data movement
|
||||||
|
; 'mov' can stay literal
|
||||||
|
%define mvi mov
|
||||||
|
%define lxi mov
|
||||||
|
%macro lda 1
|
||||||
|
mov al, byte [%1]
|
||||||
|
%endmacro
|
||||||
|
%macro sta 1
|
||||||
|
mov byte [%1], al
|
||||||
|
%endmacro
|
||||||
|
%macro lhld 1
|
||||||
|
mov bx, word [%1]
|
||||||
|
%endmacro
|
||||||
|
%macro shld 1
|
||||||
|
mov word [%1], bx
|
||||||
|
%endmacro
|
||||||
|
%macro ldax 1
|
||||||
|
mov al, byte [%1]
|
||||||
|
%endmacro
|
||||||
|
%macro stax 1
|
||||||
|
mov byte [%1], al
|
||||||
|
%endmacro
|
||||||
|
%macro xchg 1
|
||||||
|
xchg dx, bx
|
||||||
|
%endmacro
|
||||||
|
; addition
|
||||||
|
%macro add 1
|
||||||
|
add al, %1
|
||||||
|
%endmacro
|
||||||
|
%macro adi 1
|
||||||
|
add al, %1
|
||||||
|
%endmacro
|
||||||
|
%macro adc 1
|
||||||
|
adc al, %1
|
||||||
|
%endmacro
|
||||||
|
%macro aci 1
|
||||||
|
adc al, %1
|
||||||
|
%endmacro
|
||||||
|
; subtraction
|
||||||
|
%macro sub 1
|
||||||
|
sub al, %1
|
||||||
|
%endmacro
|
||||||
|
%macro sui 1
|
||||||
|
sub al, %1
|
||||||
|
%endmacro
|
||||||
|
%macro sbb 1
|
||||||
|
sub al, %1
|
||||||
|
%endmacro
|
||||||
|
%macro sbi 1
|
||||||
|
sub al, %1
|
||||||
|
%endmacro
|
||||||
|
; increment / decrement
|
||||||
|
%define inr inc
|
||||||
|
%define dcr dec
|
||||||
|
%define inx inc
|
||||||
|
%define dcx dec
|
||||||
|
; pointer arithmetic
|
||||||
|
%macro dad 1
|
||||||
|
add bx, %1
|
||||||
|
%endmacro
|
||||||
|
; 'daa' stays literal
|
||||||
|
|
||||||
|
;ANA S 10100SSS ZSCPA AND register with A
|
||||||
|
;ANI # 11100110 db ZSPCA AND immediate with A
|
||||||
|
;ORA S 10110SSS ZSPCA OR register with A
|
||||||
|
;ORI # 11110110 ZSPCA OR immediate with A
|
||||||
|
;XRA S 10101SSS ZSPCA ExclusiveOR register with A
|
||||||
|
;XRI # 11101110 db ZSPCA ExclusiveOR immediate with A
|
||||||
|
|
||||||
|
;CMP S 10111SSS ZSPCA Compare register with A
|
||||||
|
;CPI # 11111110 ZSPCA Compare immediate with A
|
||||||
|
|
||||||
|
;RLC 00000111 C Rotate A left
|
||||||
|
;RRC 00001111 C Rotate A right
|
||||||
|
;RAL 00010111 C Rotate A left through carry
|
||||||
|
;RAR 00011111 C Rotate A right through carry
|
||||||
|
;CMA 00101111 - Compliment A
|
||||||
|
;CMC 00111111 C Compliment Carry flag
|
||||||
|
;STC 00110111 C Set Carry flag
|
||||||
|
;JMP a 11000011 lb hb - Unconditional jump
|
||||||
|
;Jccc a 11CCC010 lb hb - Conditional jump
|
||||||
|
;CALL a 11001101 lb hb - Unconditional subroutine call
|
||||||
|
;Cccc a 11CCC100 lb hb - Conditional subroutine call
|
||||||
|
;RET 11001001 - Unconditional return from subroutine
|
||||||
|
;Rccc 11CCC000 - Conditional return from subroutine
|
||||||
|
;RST n 11NNN111 - Restart (Call n*8)
|
||||||
|
;PCHL 11101001 - Jump to address in H:L
|
||||||
|
;PUSH RP 11RP0101 *2 - Push register pair on the stack
|
||||||
|
;POP RP 11RP0001 *2 *2 Pop register pair from the stack
|
||||||
|
;XTHL 11100011 - Swap H:L with top word on stack
|
||||||
|
;SPHL 11111001 - Set SP to content of H:L
|
||||||
|
;IN p 11011011 pa - Read input port into A
|
||||||
|
;OUT p 11010011 pa - Write A to output port
|
||||||
|
;EI 11111011 - Enable interrupts
|
||||||
|
;DI 11110011 - Disable interrupts
|
||||||
|
;HLT 01110110 - Halt processor
|
||||||
|
;NOP 00000000 - No operation
|
||||||
|
|
||||||
|
%macro cnz 1
|
||||||
|
jz %%skip
|
||||||
|
call near %1
|
||||||
|
%%skip:
|
||||||
|
%endmacro
|
142
lib/opcode80.asm
Normal file
142
lib/opcode80.asm
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
; BYTE name length
|
||||||
|
; n BYTES name
|
||||||
|
; BYTE opcode template (variable parts zero)
|
||||||
|
;
|
||||||
|
; BYTE operand 1
|
||||||
|
; BYTE operand 2
|
||||||
|
|
||||||
|
; operand types:
|
||||||
|
; 0x00 none
|
||||||
|
; 0x1n reg8, opcode |= (reg8 << n)
|
||||||
|
; 0x2n reg16, opcode |= (reg8 << n)
|
||||||
|
; 0x3n reg16b, opcode |= (reg8 << n)
|
||||||
|
; 0x7n 3-bit number, opcode |= (num << n)
|
||||||
|
; 0x80 imm8, encoded as extra byte
|
||||||
|
; 0x81 imm16, encoded as extra word
|
||||||
|
|
||||||
|
registers:
|
||||||
|
.reg8:
|
||||||
|
db "B", 0
|
||||||
|
db "C", 0
|
||||||
|
db "D", 0
|
||||||
|
db "E", 0
|
||||||
|
db "H", 0
|
||||||
|
db "L", 0
|
||||||
|
db "M", 0
|
||||||
|
db 0
|
||||||
|
.reg16:
|
||||||
|
db "BC", 0
|
||||||
|
db "DE", 0
|
||||||
|
db "HL", 0
|
||||||
|
db "SP", 0
|
||||||
|
db 0
|
||||||
|
.reg16b:
|
||||||
|
db "BC", 0
|
||||||
|
db "DE", 0
|
||||||
|
db "HL", 0
|
||||||
|
db "AF", 0
|
||||||
|
db 0
|
||||||
|
.end:
|
||||||
|
db 0
|
||||||
|
|
||||||
|
opcodes:
|
||||||
|
; Data movement
|
||||||
|
db 3, "MOV", 0b01000000, 0x13, 0x10
|
||||||
|
db 3, "MVI", 0b00000110, 0x13, 0x80
|
||||||
|
db 3, "LXI", 0b00000001, 0x24, 0x81
|
||||||
|
db 3, "LDA", 0b00111010, 0x81, 0x00
|
||||||
|
db 3, "STA", 0b00110010, 0x81, 0x00
|
||||||
|
db 4, "LHLD", 0b00101010, 0x81, 0x00
|
||||||
|
db 4, "SHLD", 0b00100010, 0x81, 0x00
|
||||||
|
db 4, "LDAX", 0b00001010, 0x24, 0x00
|
||||||
|
db 4, "STAX", 0b00000010, 0x24, 0x00
|
||||||
|
db 4, "XCHG", 0b11101011, 0x00, 0x00
|
||||||
|
|
||||||
|
; Addition / Subtraction
|
||||||
|
db 3, "ADD", 0b10000000, 0x10, 0x00
|
||||||
|
db 3, "ADI", 0b11000110, 0x80, 0x00
|
||||||
|
db 3, "ADC", 0b10001000, 0x10, 0x00
|
||||||
|
db 3, "ACI", 0b11001110, 0x80, 0x00
|
||||||
|
db 3, "SUB", 0b10010000, 0x10, 0x00
|
||||||
|
db 3, "SUI", 0b11010110, 0x80, 0x00
|
||||||
|
db 3, "SBB", 0b10011000, 0x10, 0x00
|
||||||
|
db 3, "SBI", 0b11011110, 0x80, 0x00
|
||||||
|
db 3, "INR", 0b00000100, 0x13, 0x00
|
||||||
|
db 3, "DCR", 0b00000101, 0x13, 0x00
|
||||||
|
db 3, "INX", 0b00000011, 0x24, 0x00
|
||||||
|
db 3, "DCX", 0b00001011, 0x24, 0x00
|
||||||
|
db 3, "DAD", 0b00001001, 0x24, 0x00
|
||||||
|
|
||||||
|
; BCD
|
||||||
|
db 3, "DAA", 0b00100111, 0x00, 0x00
|
||||||
|
|
||||||
|
; Bitwise operations
|
||||||
|
db 3, "ANA", 0b10100000, 0x10, 0x00
|
||||||
|
db 3, "ANI", 0b11100110, 0x80, 0x00
|
||||||
|
db 3, "ORA", 0b10110000, 0x10, 0x00
|
||||||
|
db 3, "ORI", 0b11110110, 0x80, 0x00
|
||||||
|
db 3, "XRA", 0b10101000, 0x10, 0x00
|
||||||
|
db 3, "XRI", 0b11101110, 0x80, 0x00
|
||||||
|
db 3, "CMP", 0b10111000, 0x10, 0x00
|
||||||
|
db 3, "CPI", 0b11111110, 0x80, 0x00
|
||||||
|
|
||||||
|
; Rotate
|
||||||
|
db 3, "RLC", 0b00000111, 0x00, 0x00
|
||||||
|
db 3, "RRC", 0b00001111, 0x00, 0x00
|
||||||
|
db 3, "RAL", 0b00010111, 0x00, 0x00
|
||||||
|
db 3, "RAR", 0b00011111, 0x00, 0x00
|
||||||
|
|
||||||
|
; Complement
|
||||||
|
db 3, "CMA", 0b00101111, 0x00, 0x00
|
||||||
|
db 3, "CMC", 0b00111111, 0x00, 0x00
|
||||||
|
db 3, "STC", 0b00110111, 0x00, 0x00
|
||||||
|
|
||||||
|
; Jump
|
||||||
|
db 3, "JMP", 0b11000011, 0x81, 0x00
|
||||||
|
db 3, "JNZ", 0b11000010, 0x81, 0x00
|
||||||
|
db 2, "JZ", 0b11001010, 0x81, 0x00
|
||||||
|
db 3, "JNC", 0b11010010, 0x81, 0x00
|
||||||
|
db 2, "JC", 0b11011010, 0x81, 0x00
|
||||||
|
db 3, "JPO", 0b11100010, 0x81, 0x00
|
||||||
|
db 3, "JPE", 0b11101010, 0x81, 0x00
|
||||||
|
db 2, "JP", 0b11110010, 0x81, 0x00
|
||||||
|
db 2, "JM", 0b11111010, 0x81, 0x00
|
||||||
|
|
||||||
|
; Call
|
||||||
|
db 4, "CALL", 0b11001101, 0x81, 0x00
|
||||||
|
db 3, "CNZ", 0b11000100, 0x81, 0x00
|
||||||
|
db 2, "CZ", 0b11001100, 0x81, 0x00
|
||||||
|
db 3, "CNC", 0b11010100, 0x81, 0x00
|
||||||
|
db 2, "CC", 0b11011100, 0x81, 0x00
|
||||||
|
db 3, "CPO", 0b11100100, 0x81, 0x00
|
||||||
|
db 3, "CPE", 0b11101100, 0x81, 0x00
|
||||||
|
db 2, "CP", 0b11110100, 0x81, 0x00
|
||||||
|
db 2, "CM", 0b11111100, 0x81, 0x00
|
||||||
|
|
||||||
|
; Return
|
||||||
|
db 3, "RET", 0b11001001, 0x00, 0x00
|
||||||
|
db 3, "RNZ", 0b11000000, 0x00, 0x00
|
||||||
|
db 2, "RZ", 0b11001000, 0x00, 0x00
|
||||||
|
db 3, "RNC", 0b11010000, 0x00, 0x00
|
||||||
|
db 2, "RC", 0b11011000, 0x00, 0x00
|
||||||
|
db 3, "RPO", 0b11100000, 0x00, 0x00
|
||||||
|
db 3, "RPE", 0b11101000, 0x00, 0x00
|
||||||
|
db 2, "RP", 0b11110000, 0x00, 0x00
|
||||||
|
db 2, "RM", 0b11111000, 0x00, 0x00
|
||||||
|
|
||||||
|
db 3, "RST", 0b11000111, 0x73, 0x00
|
||||||
|
db 4, "PCHL", 0b11101001, 0x00, 0x00
|
||||||
|
db 4, "PUSH", 0b11000101, 0x34, 0x00
|
||||||
|
db 3, "POP", 0b11000001, 0x34, 0x00
|
||||||
|
db 4, "XTHL", 0b11100011, 0x00, 0x00
|
||||||
|
db 4, "SPHL", 0b11111001, 0x00, 0x00
|
||||||
|
|
||||||
|
db 2, "IN", 0b11011011, 0x80, 0x00
|
||||||
|
db 3, "OUT", 0b11010011, 0x80, 0x00
|
||||||
|
|
||||||
|
db 2, "EI", 0b11111011, 0x00, 0x00
|
||||||
|
db 2, "DI", 0b11110011, 0x00, 0x00
|
||||||
|
db 3, "HLT", 0b01110110, 0x00, 0x00
|
||||||
|
db 3, "NOP", 0b00000000, 0x00, 0x00
|
||||||
|
|
||||||
|
db 0
|
30
lib/popcnt.asm
Normal file
30
lib/popcnt.asm
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
popcnt:
|
||||||
|
push bx
|
||||||
|
push cx
|
||||||
|
|
||||||
|
mov bx, ax
|
||||||
|
and ax, 0x5555 ; 8x 01
|
||||||
|
and bx, 0xaaaa ; 8x 10
|
||||||
|
shr bx, 1
|
||||||
|
add ax, bx
|
||||||
|
|
||||||
|
mov bx, ax
|
||||||
|
and ax, 0x3333 ; 4x 0011
|
||||||
|
and bx, 0xcccc ; 4x 1100
|
||||||
|
mov cl, 2
|
||||||
|
shr bx, cl
|
||||||
|
add ax, bx
|
||||||
|
|
||||||
|
mov bx, ax
|
||||||
|
and ax, 0x0f0f ; 2x 00001111
|
||||||
|
and bx, 0xf0f0 ; 2x 11110000
|
||||||
|
mov cl, 4
|
||||||
|
shr bx, cl
|
||||||
|
add ax, bx
|
||||||
|
|
||||||
|
add al, ah
|
||||||
|
xor ah, ah
|
||||||
|
|
||||||
|
pop cx
|
||||||
|
pop bx
|
||||||
|
ret
|
33
lib/print.asm
Normal file
33
lib/print.asm
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
; important functions in this file: kprintf
|
||||||
|
|
||||||
|
; print a word
|
||||||
|
; in: ax
|
||||||
|
print16:
|
||||||
|
xchg ah,al
|
||||||
|
call print8
|
||||||
|
xchg ah,al
|
||||||
|
|
||||||
|
; print a byte
|
||||||
|
; in: al
|
||||||
|
print8:
|
||||||
|
push ax ; avoid destroying ah
|
||||||
|
push bx
|
||||||
|
xor bx, bx
|
||||||
|
aam 16 ; high nibble moved into ah, low nibble into al
|
||||||
|
add ax, 0x3030
|
||||||
|
push ax
|
||||||
|
xchg al, ah
|
||||||
|
call .nib
|
||||||
|
pop ax
|
||||||
|
call .nib
|
||||||
|
pop bx
|
||||||
|
pop ax
|
||||||
|
ret
|
||||||
|
.nib:
|
||||||
|
cmp al, 0x3a
|
||||||
|
jl .out
|
||||||
|
add al, 0x07
|
||||||
|
.out:
|
||||||
|
mov ah, 0x0e
|
||||||
|
int 0x10
|
||||||
|
ret
|
105
lib/printf.asm
Normal file
105
lib/printf.asm
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
printf:
|
||||||
|
cld
|
||||||
|
pop si
|
||||||
|
push bp
|
||||||
|
mov bp, sp
|
||||||
|
.loop:
|
||||||
|
mov al, [cs:si]
|
||||||
|
inc si
|
||||||
|
cmp al, 0x00
|
||||||
|
je .end
|
||||||
|
cmp al, 0x25
|
||||||
|
je .handle_25h
|
||||||
|
.literal:
|
||||||
|
call putc
|
||||||
|
jmp .loop
|
||||||
|
.end:
|
||||||
|
pop bp
|
||||||
|
push si
|
||||||
|
ret
|
||||||
|
.handle_25h:
|
||||||
|
mov al, [cs:si]
|
||||||
|
inc si
|
||||||
|
cmp al, 0x25
|
||||||
|
je .literal
|
||||||
|
cmp al, 0x58 ; 'X'
|
||||||
|
je .printhex
|
||||||
|
cmp al, 0x55 ; 'U'
|
||||||
|
je .printdec
|
||||||
|
cmp al, 0x53 ; 'S'
|
||||||
|
je .printstr
|
||||||
|
mov al, 0x3F
|
||||||
|
jmp .literal
|
||||||
|
.printhex:
|
||||||
|
add bp, 2
|
||||||
|
mov ax, [bp]
|
||||||
|
mov bx, 0x0010
|
||||||
|
call print_number
|
||||||
|
jmp .loop
|
||||||
|
.printdec:
|
||||||
|
add bp, 2
|
||||||
|
mov ax, [bp]
|
||||||
|
mov bx, 0x000A
|
||||||
|
call print_number
|
||||||
|
jmp .loop
|
||||||
|
.printstr:
|
||||||
|
add bp, 2
|
||||||
|
mov ax, [bp]
|
||||||
|
call print_string
|
||||||
|
jmp .loop
|
||||||
|
|
||||||
|
; converts a integer to ascii
|
||||||
|
; in ax input integer
|
||||||
|
; bx base
|
||||||
|
; cx minimum number of digits
|
||||||
|
; out bx garbled
|
||||||
|
; dx garbled
|
||||||
|
print_number_padded:
|
||||||
|
xor dx, dx
|
||||||
|
div bx
|
||||||
|
push dx
|
||||||
|
dec cx
|
||||||
|
jz .nopad
|
||||||
|
call print_number_padded
|
||||||
|
jmp print_number.end
|
||||||
|
.nopad:
|
||||||
|
call print_number
|
||||||
|
jmp print_number.end
|
||||||
|
|
||||||
|
; converts a integer to ascii
|
||||||
|
; in ax input integer
|
||||||
|
; bx base
|
||||||
|
; out bx garbled
|
||||||
|
; dx garbled
|
||||||
|
print_number:
|
||||||
|
xor dx, dx
|
||||||
|
div bx ; ax = dx:ax / 10, dx = dx:ax % 10
|
||||||
|
push dx
|
||||||
|
and ax, ax
|
||||||
|
jz .end
|
||||||
|
call print_number
|
||||||
|
.end:
|
||||||
|
pop bx
|
||||||
|
xor bh, bh
|
||||||
|
add bx, print_chars
|
||||||
|
mov al, [cs:bx]
|
||||||
|
call putc
|
||||||
|
ret
|
||||||
|
|
||||||
|
; putc's a string
|
||||||
|
; in DS:AX null-terminated string
|
||||||
|
print_string:
|
||||||
|
push si
|
||||||
|
mov si, ax
|
||||||
|
.loop:
|
||||||
|
lodsb
|
||||||
|
cmp al, 0x00
|
||||||
|
je .end
|
||||||
|
call putc
|
||||||
|
jmp .loop
|
||||||
|
.end:
|
||||||
|
pop si
|
||||||
|
ret
|
||||||
|
|
||||||
|
print_chars:
|
||||||
|
db "0123456789ABCDEF"
|
294
rom/debug.asm
Normal file
294
rom/debug.asm
Normal file
@ -0,0 +1,294 @@
|
|||||||
|
cpu 8086
|
||||||
|
org 0x0000
|
||||||
|
|
||||||
|
%macro push8086 0
|
||||||
|
push ss
|
||||||
|
push es
|
||||||
|
push ds
|
||||||
|
push di
|
||||||
|
push si
|
||||||
|
push bp
|
||||||
|
push sp
|
||||||
|
push bx
|
||||||
|
push dx
|
||||||
|
push cx
|
||||||
|
push ax
|
||||||
|
|
||||||
|
; adjust stored SP to be value before interrupt
|
||||||
|
mov bp, sp
|
||||||
|
mov [bp+08], bp
|
||||||
|
add WORD [bp+08], 28
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro pop8086 0
|
||||||
|
pop ax
|
||||||
|
pop cx
|
||||||
|
pop dx
|
||||||
|
pop bx
|
||||||
|
add sp, 2 ; skip SP
|
||||||
|
pop bp
|
||||||
|
pop si
|
||||||
|
pop di
|
||||||
|
pop ds
|
||||||
|
pop es
|
||||||
|
add sp, 2 ; skip SS
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
rom:
|
||||||
|
db 0x55, 0xAA
|
||||||
|
.sectors:
|
||||||
|
db 0x00
|
||||||
|
.init:
|
||||||
|
jmp init
|
||||||
|
nop
|
||||||
|
|
||||||
|
.name:
|
||||||
|
db "RDOS DEBUG", 0
|
||||||
|
|
||||||
|
times (0x18 - ($-$$)) db 0
|
||||||
|
.pcir_ptr:
|
||||||
|
dw 0
|
||||||
|
|
||||||
|
times (0x1A - ($-$$)) db 0
|
||||||
|
.pnp_ptr:
|
||||||
|
dw pnp
|
||||||
|
|
||||||
|
pnp:
|
||||||
|
db "$PnP"
|
||||||
|
.version:
|
||||||
|
db 1 ; version 1
|
||||||
|
.length:
|
||||||
|
db 2 ; 2 * 16 length
|
||||||
|
dw 0 ; offset of next header
|
||||||
|
db 0
|
||||||
|
.checksum:
|
||||||
|
db 0 ; checksum (filled by fix-rom)
|
||||||
|
dd 0 ; device identifier
|
||||||
|
dw 0 ; manufacturer string
|
||||||
|
dw rom.name ; product name string
|
||||||
|
db 0,0,0 ; device type string
|
||||||
|
db 0x20 ; device indicator, bit for "read cacheable" set
|
||||||
|
dw 0 ; boot connection vector
|
||||||
|
dw 0 ; boot disconnect vector
|
||||||
|
dw 0 ; bootstrap entry point
|
||||||
|
dw 0 ; reserved
|
||||||
|
dw 0
|
||||||
|
|
||||||
|
init:
|
||||||
|
mov bx, 0
|
||||||
|
mov dx, isr_divide_error
|
||||||
|
call hook_int
|
||||||
|
|
||||||
|
mov bx, 1
|
||||||
|
mov dx, isr_singlestep
|
||||||
|
call hook_int
|
||||||
|
|
||||||
|
mov bx, 2
|
||||||
|
mov dx, isr_nmi
|
||||||
|
call hook_int
|
||||||
|
|
||||||
|
mov bx, 3
|
||||||
|
mov dx, isr_breakpoint
|
||||||
|
call hook_int
|
||||||
|
|
||||||
|
mov bx, 4
|
||||||
|
mov dx, isr_overflow
|
||||||
|
call hook_int
|
||||||
|
|
||||||
|
; 5 left out
|
||||||
|
|
||||||
|
mov bx, 6
|
||||||
|
mov dx, isr_invalid_opcode
|
||||||
|
call hook_int
|
||||||
|
|
||||||
|
push cs
|
||||||
|
pop ds
|
||||||
|
mov si, rom.name
|
||||||
|
push cs
|
||||||
|
push si
|
||||||
|
call printf
|
||||||
|
db "%S %X", 0x0A, 0x0D, 0
|
||||||
|
add sp, 4
|
||||||
|
|
||||||
|
retf
|
||||||
|
|
||||||
|
; Hook interrupt
|
||||||
|
hook_int:
|
||||||
|
; bx times 4
|
||||||
|
add bx, bx
|
||||||
|
add bx, bx
|
||||||
|
; store offset
|
||||||
|
mov [bx], dx
|
||||||
|
; store segment
|
||||||
|
push ax
|
||||||
|
mov ax, cs
|
||||||
|
mov [bx+2], ax
|
||||||
|
pop ax
|
||||||
|
ret
|
||||||
|
|
||||||
|
putc:
|
||||||
|
push bx
|
||||||
|
push cx
|
||||||
|
mov ah, 0x0e
|
||||||
|
mov bx, 0x0000
|
||||||
|
int 0x10
|
||||||
|
pop cx
|
||||||
|
pop bx
|
||||||
|
ret
|
||||||
|
|
||||||
|
; Names for words in debug frame
|
||||||
|
; Two characters per word, 14 words total
|
||||||
|
debug_frame_names:
|
||||||
|
; general-purpose registers
|
||||||
|
db "AXCXDXBXSPBPSIDI"
|
||||||
|
; extra registers
|
||||||
|
db "DSESSSIPCSFL"
|
||||||
|
|
||||||
|
; Names for bits in debug_frame+26 (FL/Flags register)
|
||||||
|
; One character per bit, 16 bits total
|
||||||
|
debug_frame_flags:
|
||||||
|
db "++++ODIT"
|
||||||
|
db "SZ+A+P+C"
|
||||||
|
|
||||||
|
; Print a single register from the frame
|
||||||
|
; in SI frame offset for register
|
||||||
|
debug_frame_register_print:
|
||||||
|
mov bx, debug_frame_names
|
||||||
|
mov al, [cs:bx+si] ; first name char load
|
||||||
|
call putc
|
||||||
|
mov al, [cs:bx+si+1] ; second name char load
|
||||||
|
call putc
|
||||||
|
mov al, '='
|
||||||
|
call putc
|
||||||
|
mov ax, [ss:bp+si] ; value load
|
||||||
|
; prepare call to print_number
|
||||||
|
push bx
|
||||||
|
push cx
|
||||||
|
mov bx, 0x0010
|
||||||
|
mov cx, 3
|
||||||
|
call print_number_padded
|
||||||
|
pop cx
|
||||||
|
pop bx
|
||||||
|
mov al, ' '
|
||||||
|
call putc
|
||||||
|
ret
|
||||||
|
|
||||||
|
debug_frame_print:
|
||||||
|
mov si, 0
|
||||||
|
mov cx, 8
|
||||||
|
.reg1loop:
|
||||||
|
call debug_frame_register_print
|
||||||
|
add si, 2
|
||||||
|
loop .reg1loop
|
||||||
|
|
||||||
|
mov dx, [ss:bp+26]
|
||||||
|
mov di, debug_frame_flags
|
||||||
|
mov cx, 0x0010
|
||||||
|
.flag_loop:
|
||||||
|
mov al, [cs:di]
|
||||||
|
inc di
|
||||||
|
cmp al, '+'
|
||||||
|
je .next
|
||||||
|
test dx, 0x8000
|
||||||
|
jnz .write
|
||||||
|
mov al, '-'
|
||||||
|
.write:
|
||||||
|
call putc
|
||||||
|
.next:
|
||||||
|
sal dx, 1
|
||||||
|
loop .flag_loop
|
||||||
|
|
||||||
|
call printf
|
||||||
|
db 0x0A, 0x0D, 0
|
||||||
|
|
||||||
|
mov si, 16
|
||||||
|
mov cx, 5
|
||||||
|
.reg2loop:
|
||||||
|
call debug_frame_register_print
|
||||||
|
add si, 2
|
||||||
|
loop .reg2loop
|
||||||
|
|
||||||
|
call printf
|
||||||
|
db 0x0A, 0x0D, 0
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
isr_divide_error:
|
||||||
|
push8086
|
||||||
|
|
||||||
|
call printf
|
||||||
|
db 0x0A, 0x0D, "INT 0 - DIVIDE ERROR", 0x0A, 0x0D, 0
|
||||||
|
|
||||||
|
call debug_frame_print
|
||||||
|
|
||||||
|
jmp halt
|
||||||
|
|
||||||
|
isr_singlestep:
|
||||||
|
push8086
|
||||||
|
|
||||||
|
call printf
|
||||||
|
db 0x0A, 0x0D, 0
|
||||||
|
|
||||||
|
call debug_frame_print
|
||||||
|
|
||||||
|
; wait for keypress
|
||||||
|
xor ax, ax
|
||||||
|
int 0x16
|
||||||
|
|
||||||
|
; enable trace flag so we fire again after next instruction
|
||||||
|
or word [ss:bp+26], 0x0100
|
||||||
|
|
||||||
|
pop8086
|
||||||
|
iret
|
||||||
|
|
||||||
|
isr_nmi:
|
||||||
|
push8086
|
||||||
|
|
||||||
|
call printf
|
||||||
|
db 0x0A, 0x0D, "INT 2 - NON-MASKABLE INTERRUPT", 0x0A, 0x0D, 0
|
||||||
|
|
||||||
|
call debug_frame_print
|
||||||
|
|
||||||
|
jmp halt
|
||||||
|
|
||||||
|
isr_breakpoint:
|
||||||
|
push8086
|
||||||
|
|
||||||
|
call printf
|
||||||
|
db 0x0A, 0x0D, 0
|
||||||
|
|
||||||
|
call debug_frame_print
|
||||||
|
|
||||||
|
pop8086
|
||||||
|
iret
|
||||||
|
|
||||||
|
isr_overflow:
|
||||||
|
push8086
|
||||||
|
|
||||||
|
call printf
|
||||||
|
db 0x0A, 0x0D, "INT 4 - OVERFLOW", 0x0A, 0x0D, 0
|
||||||
|
|
||||||
|
call debug_frame_print
|
||||||
|
|
||||||
|
jmp halt
|
||||||
|
|
||||||
|
isr_invalid_opcode:
|
||||||
|
push8086
|
||||||
|
|
||||||
|
call printf
|
||||||
|
db 0x0A, 0x0D, "INT 6 - INVALID OPCODE", 0x0A, 0x0D, 0
|
||||||
|
|
||||||
|
call debug_frame_print
|
||||||
|
|
||||||
|
jmp halt
|
||||||
|
|
||||||
|
halt:
|
||||||
|
call printf
|
||||||
|
db "HALTED", 0x0A, 0x0D, 0
|
||||||
|
.loop:
|
||||||
|
hlt
|
||||||
|
jmp halt
|
||||||
|
|
||||||
|
%include "printf.asm"
|
||||||
|
|
||||||
|
align 512
|
518
src/utils/em8080.c
Normal file
518
src/utils/em8080.c
Normal file
@ -0,0 +1,518 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
uint8_t mem[64*1024];
|
||||||
|
|
||||||
|
typedef struct flagbits {
|
||||||
|
unsigned int c : 1;
|
||||||
|
unsigned int u1 : 1;
|
||||||
|
unsigned int p : 1;
|
||||||
|
unsigned int u3 : 1;
|
||||||
|
|
||||||
|
unsigned int a : 1;
|
||||||
|
unsigned int u5 : 1;
|
||||||
|
unsigned int z : 1;
|
||||||
|
unsigned int s : 1;
|
||||||
|
} flagbits;
|
||||||
|
|
||||||
|
typedef struct reg {
|
||||||
|
uint8_t flags;
|
||||||
|
uint8_t a;
|
||||||
|
uint8_t c;
|
||||||
|
uint8_t b;
|
||||||
|
uint8_t e;
|
||||||
|
uint8_t d;
|
||||||
|
uint8_t l;
|
||||||
|
uint8_t h;
|
||||||
|
} reg;
|
||||||
|
|
||||||
|
typedef struct regp {
|
||||||
|
uint16_t psw;
|
||||||
|
uint16_t bc;
|
||||||
|
uint16_t de;
|
||||||
|
uint16_t hl;
|
||||||
|
} regp;
|
||||||
|
|
||||||
|
union regset {
|
||||||
|
struct reg reg;
|
||||||
|
struct regp regp;
|
||||||
|
} regset;
|
||||||
|
|
||||||
|
#define A regset.reg.a
|
||||||
|
#define B regset.reg.b
|
||||||
|
#define C regset.reg.c
|
||||||
|
#define D regset.reg.d
|
||||||
|
#define E regset.reg.e
|
||||||
|
#define H regset.reg.h
|
||||||
|
#define L regset.reg.l
|
||||||
|
#define M mem[HL]
|
||||||
|
|
||||||
|
#define BC regset.regp.bc
|
||||||
|
#define DE regset.regp.de
|
||||||
|
#define HL regset.regp.hl
|
||||||
|
|
||||||
|
#define flags (*(struct flagbits*)®set.reg.flags)
|
||||||
|
|
||||||
|
uint16_t IP = 0x100;
|
||||||
|
uint16_t SP = 0;
|
||||||
|
unsigned int tmp;
|
||||||
|
|
||||||
|
// Dump registers
|
||||||
|
void dump() {
|
||||||
|
printf("\n");
|
||||||
|
printf("A=%02X BC=%04X DE=%04X HL=%04X M=%02X SP=%04X ", A, BC, DE, HL, M, SP);
|
||||||
|
printf("%c", flags.s ? 'S' : '-');
|
||||||
|
printf("%c", flags.z ? 'Z' : '-');
|
||||||
|
printf("%c", flags.a ? 'A' : '-');
|
||||||
|
printf("%c", flags.p ? 'P' : '-');
|
||||||
|
printf("%c", flags.c ? 'C' : '-');
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
printf("IP=%04X : %02X %02X\n", IP, mem[IP], mem[IP+1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t imm8() {
|
||||||
|
uint8_t r = *(uint8_t*)&mem[IP];
|
||||||
|
IP++;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t imm16() {
|
||||||
|
uint16_t r = *(uint16_t*)&mem[IP];
|
||||||
|
IP+=2;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void push(uint16_t v) {
|
||||||
|
SP -= 2;
|
||||||
|
*(uint16_t*)&mem[SP] = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t pop() {
|
||||||
|
uint16_t v = *(uint16_t*)&mem[SP];
|
||||||
|
SP += 2;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
void in(uint8_t port) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void out(uint8_t port) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int has_even_parity(uint8_t x){
|
||||||
|
unsigned int count = 0, i, b = 1;
|
||||||
|
|
||||||
|
for(i = 0; i < 8; i++){
|
||||||
|
if( x & (b << i) ){count++;}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( (count % 2) ){return 0;}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cpm_syscall(int number) {
|
||||||
|
switch(number) {
|
||||||
|
case 0:
|
||||||
|
exit(0);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
printf("%c", E);
|
||||||
|
break;
|
||||||
|
case 0x0C:
|
||||||
|
H=0x02;
|
||||||
|
L=0x00;
|
||||||
|
break;;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "Fatal: Unhandled CP/M syscall C=%02Xh\n", number);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void call(uint16_t v) {
|
||||||
|
switch(v) {
|
||||||
|
case 0:
|
||||||
|
exit(0);
|
||||||
|
break;;
|
||||||
|
case 5:
|
||||||
|
cpm_syscall(C);
|
||||||
|
break;;
|
||||||
|
default:
|
||||||
|
push(IP);
|
||||||
|
IP=v;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void interrupt(int number) {
|
||||||
|
call(number << 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define add16c(a, b) \
|
||||||
|
tmp = a + b; \
|
||||||
|
flags.c = (tmp >> 16) & 1
|
||||||
|
|
||||||
|
#define unarync(a, op) \
|
||||||
|
tmp=a; \
|
||||||
|
tmp op; \
|
||||||
|
flags.p = has_even_parity(tmp & 8); \
|
||||||
|
flags.z = !(tmp); \
|
||||||
|
flags.s = (tmp >> 7) & 1; \
|
||||||
|
a=tmp
|
||||||
|
|
||||||
|
#define aritht(a, op, b) \
|
||||||
|
tmp=a; \
|
||||||
|
tmp=a op b; \
|
||||||
|
flags.c = (tmp >> 8) & 1; \
|
||||||
|
flags.p = has_even_parity(tmp & 8); \
|
||||||
|
flags.z = !(tmp); \
|
||||||
|
flags.s = (tmp >> 7) & 1;
|
||||||
|
|
||||||
|
#define arith(a, op, b) \
|
||||||
|
aritht(a, op, b); \
|
||||||
|
a=tmp
|
||||||
|
|
||||||
|
// Execute a single instruction
|
||||||
|
void step() {
|
||||||
|
uint8_t opcode = mem[IP];
|
||||||
|
IP++;
|
||||||
|
switch(opcode) {
|
||||||
|
case 0x00: break;;
|
||||||
|
case 0x01: BC=imm16(); break;;
|
||||||
|
case 0x02: mem[BC]=A; break;;
|
||||||
|
case 0x03: BC++;
|
||||||
|
case 0x04: unarync(B, ++); break;;
|
||||||
|
case 0x05: unarync(B, --); break;;
|
||||||
|
case 0x06: B=imm8(); break;;
|
||||||
|
case 0x07: tmp=A; A = A << 1 | flags.c; flags.c = tmp >> 7; break;;
|
||||||
|
|
||||||
|
case 0x09: HL=add16c(HL,BC); break;;
|
||||||
|
case 0x0a: A=mem[BC]; break;;
|
||||||
|
case 0x0b: BC--;
|
||||||
|
case 0x0c: unarync(B, ++); break;;
|
||||||
|
case 0x0d: unarync(B, --); break;;
|
||||||
|
case 0x0e: C=imm8(); break;;
|
||||||
|
|
||||||
|
case 0x11: DE=imm16(); break;;
|
||||||
|
case 0x12: mem[DE]=A; break;;
|
||||||
|
case 0x13: DE++;
|
||||||
|
case 0x14: unarync(D, ++); break;;
|
||||||
|
case 0x15: unarync(D, --); break;;
|
||||||
|
case 0x16: D=imm8(); break;;
|
||||||
|
|
||||||
|
case 0x19: HL=add16c(HL,DE); break;;
|
||||||
|
case 0x1a: A=mem[DE]; break;;
|
||||||
|
case 0x1b: DE--;
|
||||||
|
case 0x1c: unarync(E, ++); break;;
|
||||||
|
case 0x1d: unarync(E, --); break;;
|
||||||
|
case 0x1e: E=imm8(); break;;
|
||||||
|
|
||||||
|
case 0x21: HL=imm16(); break;;
|
||||||
|
case 0x22: *(uint16_t*)&mem[imm16()]=HL; break;;
|
||||||
|
case 0x23: HL++;
|
||||||
|
case 0x24: unarync(H, ++); break;;
|
||||||
|
case 0x25: unarync(H, --); break;;
|
||||||
|
case 0x26: H=imm8(); break;;
|
||||||
|
|
||||||
|
case 0x29: HL=add16c(HL,HL); break;;
|
||||||
|
case 0x2a: HL=*(uint16_t*)&mem[imm16()]; break;;
|
||||||
|
case 0x2b: HL--;
|
||||||
|
case 0x2c: unarync(L, ++); break;;
|
||||||
|
case 0x2d: unarync(L, --); break;;
|
||||||
|
case 0x2e: L=imm8(); break;;
|
||||||
|
case 0x2f: A=~A; break;;
|
||||||
|
|
||||||
|
case 0x31: SP=imm16(); break;;
|
||||||
|
case 0x32: mem[imm16()]=A; break;;
|
||||||
|
case 0x33: SP++;
|
||||||
|
case 0x34: unarync(M, ++); break;;
|
||||||
|
case 0x35: unarync(M, --); break;;
|
||||||
|
case 0x36: M=imm8(); break;;
|
||||||
|
case 0x37: flags.c = 1; break;;
|
||||||
|
|
||||||
|
case 0x39: HL=add16c(HL,SP); break;;
|
||||||
|
case 0x3a: A=mem[imm16()]; break;;
|
||||||
|
case 0x3b: SP--;
|
||||||
|
case 0x3c: unarync(A, ++); break;;
|
||||||
|
case 0x3d: unarync(A, --); break;;
|
||||||
|
case 0x3e: A=imm8(); break;;
|
||||||
|
case 0x3f: flags.c = !flags.c; break;;
|
||||||
|
|
||||||
|
case 0x40: B=B; break;;
|
||||||
|
case 0x41: B=C; break;;
|
||||||
|
case 0x42: B=D; break;;
|
||||||
|
case 0x43: B=E; break;;
|
||||||
|
case 0x44: B=H; break;;
|
||||||
|
case 0x45: B=L; break;;
|
||||||
|
case 0x46: B=M; break;;
|
||||||
|
case 0x47: B=A; break;;
|
||||||
|
|
||||||
|
case 0x48: C=B; break;;
|
||||||
|
case 0x49: C=C; break;;
|
||||||
|
case 0x4a: C=D; break;;
|
||||||
|
case 0x4b: C=E; break;;
|
||||||
|
case 0x4c: C=H; break;;
|
||||||
|
case 0x4d: C=L; break;;
|
||||||
|
case 0x4e: C=M; break;;
|
||||||
|
case 0x4f: C=A; break;;
|
||||||
|
|
||||||
|
case 0x50: D=B; break;;
|
||||||
|
case 0x51: D=C; break;;
|
||||||
|
case 0x52: D=D; break;;
|
||||||
|
case 0x53: D=E; break;;
|
||||||
|
case 0x54: D=H; break;;
|
||||||
|
case 0x55: D=L; break;;
|
||||||
|
case 0x56: D=M; break;;
|
||||||
|
case 0x57: D=A; break;;
|
||||||
|
|
||||||
|
case 0x58: E=B; break;;
|
||||||
|
case 0x59: E=C; break;;
|
||||||
|
case 0x5a: E=D; break;;
|
||||||
|
case 0x5b: E=E; break;;
|
||||||
|
case 0x5c: E=H; break;;
|
||||||
|
case 0x5d: E=L; break;;
|
||||||
|
case 0x5e: E=M; break;;
|
||||||
|
case 0x5f: E=A; break;;
|
||||||
|
|
||||||
|
case 0x60: H=B; break;;
|
||||||
|
case 0x61: H=C; break;;
|
||||||
|
case 0x62: H=D; break;;
|
||||||
|
case 0x63: H=E; break;;
|
||||||
|
case 0x64: H=H; break;;
|
||||||
|
case 0x65: H=L; break;;
|
||||||
|
case 0x66: H=M; break;;
|
||||||
|
case 0x67: H=A; break;;
|
||||||
|
|
||||||
|
case 0x68: L=B; break;;
|
||||||
|
case 0x69: L=C; break;;
|
||||||
|
case 0x6a: L=D; break;;
|
||||||
|
case 0x6b: L=E; break;;
|
||||||
|
case 0x6c: L=H; break;;
|
||||||
|
case 0x6d: L=L; break;;
|
||||||
|
case 0x6e: L=M; break;;
|
||||||
|
case 0x6f: L=A; break;;
|
||||||
|
|
||||||
|
case 0x70: M=B; break;;
|
||||||
|
case 0x71: M=C; break;;
|
||||||
|
case 0x72: M=D; break;;
|
||||||
|
case 0x73: M=E; break;;
|
||||||
|
case 0x74: M=H; break;;
|
||||||
|
case 0x75: M=L; break;;
|
||||||
|
case 0x76: exit(0); break;;
|
||||||
|
case 0x77: M=A; break;;
|
||||||
|
|
||||||
|
case 0x78: A=B; break;;
|
||||||
|
case 0x79: A=C; break;;
|
||||||
|
case 0x7a: A=D; break;;
|
||||||
|
case 0x7b: A=E; break;;
|
||||||
|
case 0x7c: A=H; break;;
|
||||||
|
case 0x7d: A=L; break;;
|
||||||
|
case 0x7e: A=M; break;;
|
||||||
|
case 0x7f: A=A; break;;
|
||||||
|
|
||||||
|
case 0x80: arith(A, +, B); break;;
|
||||||
|
case 0x81: arith(A, +, C); break;;
|
||||||
|
case 0x82: arith(A, +, D); break;;
|
||||||
|
case 0x83: arith(A, +, E); break;;
|
||||||
|
case 0x84: arith(A, +, H); break;;
|
||||||
|
case 0x85: arith(A, +, L); break;;
|
||||||
|
case 0x86: arith(A, +, M); break;;
|
||||||
|
case 0x87: arith(A, +, A); break;;
|
||||||
|
|
||||||
|
case 0x88: arith(A, +flags.c+, B); break;;
|
||||||
|
case 0x89: arith(A, +flags.c+, C); break;;
|
||||||
|
case 0x8A: arith(A, +flags.c+, D); break;;
|
||||||
|
case 0x8B: arith(A, +flags.c+, E); break;;
|
||||||
|
case 0x8C: arith(A, +flags.c+, H); break;;
|
||||||
|
case 0x8D: arith(A, +flags.c+, L); break;;
|
||||||
|
case 0x8E: arith(A, +flags.c+, M); break;;
|
||||||
|
case 0x8F: arith(A, +flags.c+, A); break;;
|
||||||
|
|
||||||
|
case 0x90: arith(A, -, B); break;;
|
||||||
|
case 0x91: arith(A, -, C); break;;
|
||||||
|
case 0x92: arith(A, -, D); break;;
|
||||||
|
case 0x93: arith(A, -, E); break;;
|
||||||
|
case 0x94: arith(A, -, H); break;;
|
||||||
|
case 0x95: arith(A, -, L); break;;
|
||||||
|
case 0x96: arith(A, -, M); break;;
|
||||||
|
case 0x97: arith(A, -, A); break;;
|
||||||
|
|
||||||
|
case 0x98: arith(A, -flags.c-, B); break;;
|
||||||
|
case 0x99: arith(A, -flags.c-, C); break;;
|
||||||
|
case 0x9A: arith(A, -flags.c-, D); break;;
|
||||||
|
case 0x9B: arith(A, -flags.c-, E); break;;
|
||||||
|
case 0x9C: arith(A, -flags.c-, H); break;;
|
||||||
|
case 0x9D: arith(A, -flags.c-, L); break;;
|
||||||
|
case 0x9E: arith(A, -flags.c-, M); break;;
|
||||||
|
case 0x9F: arith(A, -flags.c-, A); break;;
|
||||||
|
|
||||||
|
case 0xA0: arith(A, &, B); break;;
|
||||||
|
case 0xA1: arith(A, &, C); break;;
|
||||||
|
case 0xA2: arith(A, &, D); break;;
|
||||||
|
case 0xA3: arith(A, &, E); break;;
|
||||||
|
case 0xA4: arith(A, &, H); break;;
|
||||||
|
case 0xA5: arith(A, &, L); break;;
|
||||||
|
case 0xA6: arith(A, &, M); break;;
|
||||||
|
case 0xA7: arith(A, &, A); break;;
|
||||||
|
|
||||||
|
case 0xA8: arith(A, ^, B); break;;
|
||||||
|
case 0xA9: arith(A, ^, C); break;;
|
||||||
|
case 0xAA: arith(A, ^, D); break;;
|
||||||
|
case 0xAB: arith(A, ^, E); break;;
|
||||||
|
case 0xAC: arith(A, ^, H); break;;
|
||||||
|
case 0xAD: arith(A, ^, L); break;;
|
||||||
|
case 0xAE: arith(A, ^, M); break;;
|
||||||
|
case 0xAF: arith(A, ^, A); break;;
|
||||||
|
|
||||||
|
case 0xB0: arith(A, |, B); break;;
|
||||||
|
case 0xB1: arith(A, |, C); break;;
|
||||||
|
case 0xB2: arith(A, |, D); break;;
|
||||||
|
case 0xB3: arith(A, |, E); break;;
|
||||||
|
case 0xB4: arith(A, |, H); break;;
|
||||||
|
case 0xB5: arith(A, |, L); break;;
|
||||||
|
case 0xB6: arith(A, |, M); break;;
|
||||||
|
case 0xB7: arith(A, |, A); break;;
|
||||||
|
|
||||||
|
case 0xB8: aritht(A, -, B); break;;
|
||||||
|
case 0xB9: aritht(A, -, C); break;;
|
||||||
|
case 0xBA: aritht(A, -, D); break;;
|
||||||
|
case 0xBB: aritht(A, -, E); break;;
|
||||||
|
case 0xBC: aritht(A, -, H); break;;
|
||||||
|
case 0xBD: aritht(A, -, L); break;;
|
||||||
|
case 0xBE: aritht(A, -, M); break;;
|
||||||
|
case 0xBF: aritht(A, -, A); break;;
|
||||||
|
|
||||||
|
case 0xC0: if (!flags.z) IP=pop(); break;;
|
||||||
|
case 0xC1: BC=pop(); break;;
|
||||||
|
case 0xC2: tmp=imm16(); if (!flags.z) IP=tmp; break;;
|
||||||
|
case 0xC3: IP=imm16(); break;;
|
||||||
|
case 0xC4: tmp=imm16(); if (!flags.z) call(tmp); break;;
|
||||||
|
case 0xC5: push(BC); break;;
|
||||||
|
case 0xC6: arith(A, +, imm8()); break;;
|
||||||
|
case 0xC7: interrupt(0); break;;
|
||||||
|
|
||||||
|
case 0xC8: if (flags.z) IP=pop(); break;;
|
||||||
|
case 0xC9: IP=pop(); break;;
|
||||||
|
case 0xCA: tmp=imm16(); if (flags.z) IP=tmp; break;;
|
||||||
|
case 0xCC: tmp=imm16(); if (flags.z) call(tmp); break;;
|
||||||
|
case 0xCD: call(imm16()); break;;
|
||||||
|
case 0xCE: arith(A, +flags.c+, imm8()); break;;
|
||||||
|
case 0xCF: interrupt(1); break;;
|
||||||
|
|
||||||
|
case 0xD0: if (!flags.c) IP=pop(); break;;
|
||||||
|
case 0xD1: DE=pop(); break;;
|
||||||
|
case 0xD2: tmp=imm16(); if (!flags.c) IP=tmp; break;;
|
||||||
|
case 0xD3: out(imm8()); break;;
|
||||||
|
case 0xD4: tmp=imm16(); if (!flags.c) call(tmp); break;;
|
||||||
|
case 0xD5: push(DE); break;;
|
||||||
|
case 0xD6: arith(A, -, imm8()); break;;
|
||||||
|
case 0xD7: interrupt(2); break;;
|
||||||
|
|
||||||
|
case 0xD8: if (flags.c) IP=pop(); break;;
|
||||||
|
case 0xDA: tmp=imm16(); if (flags.c) IP=tmp; break;;
|
||||||
|
case 0xDB: in(imm8()); break;;
|
||||||
|
case 0xDC: tmp=imm16(); if (flags.c) call(tmp); break;;
|
||||||
|
case 0xDE: arith(A, -flags.c-, imm8()); break;;
|
||||||
|
case 0xDF: interrupt(3); break;;
|
||||||
|
|
||||||
|
case 0xE0: if (!flags.p) IP=pop(); break;;
|
||||||
|
case 0xE1: HL=pop(); break;;
|
||||||
|
case 0xE2: tmp=imm16(); if (!flags.p) IP=tmp; break;;
|
||||||
|
case 0xE3: tmp=HL; HL=pop(); push(tmp); break;;
|
||||||
|
case 0xE4: tmp=imm16(); if (!flags.p) call(tmp); break;;
|
||||||
|
case 0xE5: push(HL); break;;
|
||||||
|
case 0xE6: arith(A, &, imm8()); break;;
|
||||||
|
case 0xE7: interrupt(4); break;;
|
||||||
|
|
||||||
|
case 0xE8: if (flags.p) IP=pop(); break;;
|
||||||
|
case 0xE9: IP=HL; break;;
|
||||||
|
case 0xEA: tmp=imm16(); if (flags.p) IP=tmp; break;;
|
||||||
|
case 0xEB: tmp=HL; HL=DE; DE=tmp;; break;;
|
||||||
|
case 0xEC: tmp=imm16(); if (flags.p) call(tmp); break;;
|
||||||
|
case 0xEE: arith(A, ^, imm8()); break;;
|
||||||
|
case 0xEF: interrupt(5); break;;
|
||||||
|
|
||||||
|
case 0xF0: if (!flags.s) IP=pop(); break;;
|
||||||
|
case 0xF1: regset.regp.psw=pop(); break;;
|
||||||
|
case 0xF2: tmp=imm16(); if (!flags.s) IP=tmp; break;;
|
||||||
|
case 0xF4: tmp=imm16(); if (!flags.s) call(tmp); break;;
|
||||||
|
case 0xF5: push(regset.regp.psw); break;;
|
||||||
|
case 0xF6: arith(A, |, imm8()); break;;
|
||||||
|
case 0xF7: interrupt(6); break;;
|
||||||
|
|
||||||
|
case 0xF8: if (flags.s) IP=pop(); break;;
|
||||||
|
case 0xF9: SP=HL; break;;
|
||||||
|
case 0xFA: tmp=imm16(); if (flags.s) IP=tmp; break;;
|
||||||
|
case 0xFC: tmp=imm16(); if (flags.s) call(tmp); break;;
|
||||||
|
case 0xFE: aritht(A, -, imm8()); break;;
|
||||||
|
case 0xFF: interrupt(7); break;;
|
||||||
|
|
||||||
|
default:
|
||||||
|
IP--;
|
||||||
|
dump();
|
||||||
|
fprintf(stderr, "Invalid opcode at IP=%04X\n", IP);
|
||||||
|
exit(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void copy_cmdline(char* str) {
|
||||||
|
int i, c;
|
||||||
|
uint8_t *len = &mem[0x80];
|
||||||
|
char* ptr = (char*)&mem[0x81];
|
||||||
|
c = strlen(str);
|
||||||
|
// Clip at max length
|
||||||
|
if (c>0x7E) {
|
||||||
|
fprintf(stderr, "Command line too long, max is 126 bytes\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
memcpy(ptr, str, c);
|
||||||
|
ptr[c]=0x0D;
|
||||||
|
*len=c;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
memset(&mem, sizeof(mem), 0);
|
||||||
|
// Prepare default exit into int 20h
|
||||||
|
mem[0]=0x76;
|
||||||
|
push(0);
|
||||||
|
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
|
||||||
|
while(argc && argv[0][0]=='-') {
|
||||||
|
switch(argv[0][1]) {
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "Unknown option %s\n", argv[0]);
|
||||||
|
exit(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc) {
|
||||||
|
FILE* fd = fopen(argv[0], "r");
|
||||||
|
fread(mem + IP, 1, sizeof(mem) - IP, fd);
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "No COM file specified\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc) {
|
||||||
|
copy_cmdline(argv[0]);
|
||||||
|
} else {
|
||||||
|
copy_cmdline("");
|
||||||
|
}
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
dump();
|
||||||
|
step();
|
||||||
|
}
|
||||||
|
}
|
37
src/utils/fix-rom.c
Normal file
37
src/utils/fix-rom.c
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct stat sbuf;
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
FILE* fd = fopen(argv[1], "r+");
|
||||||
|
fstat(fileno(fd), &sbuf);
|
||||||
|
if (sbuf.st_size & 0x1F) {
|
||||||
|
fprintf(stderr, "Filesize is not a multiple of 512 bytes\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill out filesize flag
|
||||||
|
fseek(fd, 2, SEEK_SET);
|
||||||
|
fputc(sbuf.st_size >> 9, fd);
|
||||||
|
|
||||||
|
// Calculate checksum
|
||||||
|
fseek(fd, 0, SEEK_SET);
|
||||||
|
off_t i;
|
||||||
|
uint8_t s;
|
||||||
|
for (i=0; i<sbuf.st_size; i++) {
|
||||||
|
s+=fgetc(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Edit last byte so that checksum is 0
|
||||||
|
fseek(fd, -1, SEEK_END);
|
||||||
|
s=fgetc(fd)-s;
|
||||||
|
fseek(fd, -1, SEEK_END);
|
||||||
|
fputc(s, fd);
|
||||||
|
|
||||||
|
fclose(fd);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user