Special Feature: ColorForth Commentary

ColorForth: BOOT.ASM

Original file

NOTICE: This is a work in progress. Parts of my commentary are still very rough. However, I have it up on the web because even in this rough form it may be useful to ColorForth enthusiasts. Expect the contents of these files to change frequently.

Boot-sector tables

; floppy boot segment

org 0 ; actually 7c00

start:
	jmp	start0
	nop

	db	'cmcf 1.0'
	dw	512          ; bytes/sector
	db	1            ; sector/cluster
	dw	1            ; sector reserved
	db	2            ; fats
	dw	16*14        ; root directory entries
	dw	80*2*18      ; sectors
	db	0f0h         ; media
	dw	9            ; sectors/fat
	dw	18           ; sectors/track
	dw	2            ; heads
	dd	0            ; hidden sectors
	dd	80*2*18      ; sectors again
	db	0            ; drive
;	db	0
;	db	29h          ; signature
;	dd	44444444h    ; serial
;	db	'color forth'; label
;	db	'		'

;.............................................................................
; Refs -- start: loc, relocate, nc_, xy_, fov_, sps, last, octal

command
	db	0
	db	0            ; head, drive

cylinder
	db	0
	db	0            ; head
	db	1            ; sector
	db	2            ; 512 bytes/sector
	db	18           ; sectors/track
	db	1bh          ; gap
	db	0ffh

align 4
nc:	dd	9            ; forth+icons+blocks 24-161 ; Number of cylinders

;.............................................................................
; Refs:
; -- command: cmd, dma
; -- cylinder: cold, spin, flop
; -- nc: cold, nc_

[Dissect bitfields in this GDT -- privilege level, start address, granularity, segment size, etc.]

gdt:	dw	17h
	dd	offset gdt0

align 8
gdt0:	dw	0, 0, 0, 0
	dw	0ffffh, 0, 9a00h, 0cfh ; code
	dw	0ffffh, 0, 9200h, 0cfh ; data

;.............................................................................
; Refs:
; -- gdt: relocate
; -- gdt0: gdt

Booting the system

; code is compiled in protected 32-bit mode.
; hence  org $-2  to fix 16-bit words
; and 4 hand-assembled instructions.
; and eax and ax exchanged
; this code is in real 16-bit mode

start0:
	mov	eax, 4f02h ; video mode
org $-2
	mov	ebx, vesa ; hp*vp rgb: 565
org $-2
	int	10h
	cli
	xor	ax, ax	; move code to 0
	mov	bx, ax
	mov	ebx, cs
	mov	ds, ebx
	mov	es, eax
	mov	di, ax
	mov	si, ax
	call	$+5 ; where are we? ip+4*cs

org $-2
loc:	pop	esi
	sub	esi, offset loc-offset start
org $-2
	mov	ecx, 512/4
org $-2
	rep	movsw
;	jmp	0:relocate
	db	0eah
	dw	offset relocate-offset start, 0

;.............................................................................
; Refs:
; -- start0: start
; -- loc: loc

relocate: ; this code is executed from 0
	mov	ds, eax
;	lgdt fword ptr gdt
	db	0fh, 1, 16h
	dw	offset gdt-offset start
	mov	al, 1
	mov	cr0, eax
;	jmp	8:protected
	db	0eah
	dw	offset protected-offset start, 8

protected: ; now in protected 32-bit mode
	mov	al, 10h
	mov	ds, eax
	mov	es, eax
	mov	ss, eax
	mov	esp, gods
	xor	ecx, ecx

;.............................................................................
; Refs:
; -- relocate: loc
; -- protected: relocate

a20:	mov	al, 0d1h
	out	64h, al
@@:	in	al, 64h
	and	al, 2
	jnz	@b
	mov	al, 4bh
	out	60h, al
	call	dma
	shl	ebx, 4
	add	esi, ebx
	cmp	dword ptr [esi], 44444444h ; boot?
	jnz	cold
	mov	cx, 63*100h-80h ; nope
	rep	movsd
	mov	esi, godd
	jmp	start2

cold:	call	sense_
	jns	cold
	mov	esi, godd
	xor	edi, edi ; cylinder 0 on top of address 0
	mov	cl, byte ptr nc
@@:	push	ecx
	call	read
	inc	cylinder
	pop	ecx
	loop	@b

start2:	call	stop
	jmp	start1

;.............................................................................
; Refs:
; -- a20: none
; -- cold: cold, a20
; -- start2: a20

Floppy driver

us equ 1000/6
ms equ 1000*us

;.............................................................................
; Refs:
; -- us: ms, (delay)
; -- ms: spin

spin:
;[Refs: flop]
	mov	cl, 1ch
	call	onoff
;	mov	dx, 3f2h
;	out	dx, al
@@:	call	sense_
	jns	@b
	mov	cylinder, 0 ; calibrate
	mov	al, 7
	mov	cl, 2
	call	cmd
	mov	ecx, 500*ms
@@:	loop	@b

cmdi:
;[Refs: cmdi, seekf]
	call	sense_
	js	cmdi
	ret

ready:
;[Refs: cmd1, sense_, read, write, readyf]
	;call	delay
	mov	dx, 3f4h
@@:	in	al, dx
	out	0e1h, al
	shl	al, 1
	jnc	@b
	lea	edx, [edx+1]
	ret

transfer:
;[Refs: read, write]
	mov	cl, 9

cmd:
;[Refs: sense_, dma, seekf, spin]
	lea	edx, command
	mov	[edx], al

cmd0:
;[Refs: cmdf]
	push	esi
	mov	esi, edx

cmd1:
;[Refs: cmd1]
	call	ready
	jns	@f
	in	al, dx
	jmp	cmd1
@@:	lodsb
	out	dx, al
	out	0e1h, al
	loop	cmd1
	pop	esi

;delay:
;[Refs: seekf, ready]
;	mov	eax, us
;@@:	dec	eax
;	jnz	@b
	ret

sense_:
;[Refs: seek, cold, spin, cmdi]
	mov	al, 8
	mov	ecx, 1
	call	cmd
@@:	call	ready
	jns	@b
	in	al, dx
	out	0e1h, al
	and	al, al
;	cmp	al, 80h
	ret

seek:
;[Refs: seek, dma, read, write, seekf]
	call	sense_
	jns	seek
	ret

stop:
;[Refs: start2, forth2]
	mov	cl, 0ch ; motor off

onoff:
;[Refs: spin]
	dup_
	mov	al, cl
	mov	dx, 3f2h
	out	dx, al
	out	0e1h, al
	drop
	ret

dma:
;[Refs: a20]
	mov	word ptr command+1, 3a2h ; l2 s6 u32 ms (e 2)
	mov	al, 3 ; timing
	mov	cl, 3
	call	cmd
	mov	word ptr command+1, 7000h ; +seek -fifo -poll
	mov	al, 13h ; configure
	mov	cl, 4
	call	cmd
	mov	dword ptr command, ecx ; 0
	ret

read:
;[Refs: cold, readf]
	call	seek
	mov	al, 0e6h ; read normal data
	call	transfer
	mov	cx, 18*2*512
@@:	call	ready
	in	al, dx
	out	0e1h, al
	stosb
	next	@b
	ret

write:
;[Refs: writef]
	call	seek
	mov	al, 0c5h ; write data
	call	transfer
	mov	cx, 18*2*512
@@:	call	ready
	lodsb
	out	dx, al
	out	0e1h, al
	next	@b
	ret

org 1feh ; mark boot sector
	dw 0aa55h
	dd 44444444h ; mark color.com

flop:
;[Refs: readf, writef, seekf]
	mov	cylinder, al ; c-cx
	dup_
	mov	dx, 3f2h
	in	al, dx
	out	0e1h, al
	test	al, 10h
	jnz	@f
	jmp	spin
@@: ret

readf: ;"read"
;[Refs: forth2]
	call	flop ; ac-ac
	push	edi
	mov	edi, [esi+4]
	shl	edi, 2
	call	read
	pop	edi

readf1:
;[Refs: writef]
	drop
	inc	eax
	add	dword ptr [esi], 1200h
	ret

writef: ;"write"
;[Refs: forth2]
	call	flop ; ac-ac
	push	esi
	mov	esi, [esi+4]
	shl	esi, 2
	call	write
	pop	esi
	jmp	readf1

seekf: ;"seek"
;[Refs: forth2]
	call	flop ; c-c
;	call	delay
	call	seek
	mov	al, 0fh
	mov	cl, 3
	call	cmd
	call	cmdi
	drop
	ret

cmdf: ;"command"
;[Refs: forth2]
	mov	ecx, eax ; an
	drop
	lea	edx, [eax*4]
	call	cmd0
	drop
	ret

readyf: ;"ready"
;[Refs: forth2]
	dup_
	call	ready
	drop
	ret

Check the index for other entries.