.define begtext, begdata, begbss
.data
begdata: 
.asciz	"(null)"
.bss
begbss: 
BOOTOFF	   =	0x7C00
LOADSEG    =	0x1000
BUFFER	   =	0x0600
PENTRYSIZE =	    16
DSKBASE    =	   120
DSKPARSIZE =	    11
SECTORS	   =	     4
a_flags	   =	     2
a_text	   =	     8
a_data	   =	    12
a_bss	   =	    16
a_total	   =	    24
A_SEP	   =	  0x20
.extern _cseg, _dseg, _runsize, _edata, _end
.extern _device, _dskpars, _heads, _sectors
.extern _eqscancode
.extern _rem_part
.text
begtext: 
.extern _boot, _printk
jmpi boot, LOADSEG+3
.space	11
jmpi boot, LOADSEG+2
boot: 
mov	ax, #LOADSEG
mov	ds, ax
movb	al, a_flags
testb	al, #A_SEP
jnz	sepID
comID: xor	ax, ax
xchg	ax, a_text
add	a_data, ax
sepID: 
mov	ax, a_total
and	ax, #0xFFFE
mov	a_total, ax
cli
mov	sp, ax
mov	ax, a_text
movb	cl, #4
shr	ax, cl
mov	cx, cs
add	ax, cx
mov	ds, ax
mov	ss, ax
sti
push	es
mov	es, ax
cld
xor	ax, ax
mov	di, #_edata
mov	cx, #_end
sub	cx, di
shr	cx, #1
rep
stow
xorb	dh, dh
mov	_device, dx
mov	_rem_part+0, si
pop	_rem_part+2
mov	_cseg, cs
mov	_dseg, ds
push	ds
mov	ax, #LOADSEG
mov	ds, ax
mov	ax, a_total+0
mov	dx, a_total+2
add	ax, a_text+0
adc	dx, a_text+2
pop	ds
mov	_runsize+0, ax
mov	_runsize+2, dx
call	_boot
.define _exit, __exit, _main
.define _reboot
_exit: 
__exit: 
_main: 
_reboot: 
mov	ax, #any_key
push	ax
call	_printk
call	_getchar
int	0x19
.data
any_key: 
.asciz	"\nHit any key to reboot\n"
.text
.define _raw_copy
_raw_copy: 
mov	bx, sp
push	si
push	di
mov	cx, 10(bx)
les	di, 2(bx)
lds	si, 6(bx)
shr	cx, #1
jb	bytecopy
rep
movw
j copydone
bytecopy: 
rcl	cx, #1
rep
movb
copydone: 
mov	ax, ss
mov	ds, ax
mov	es, ax
pop	di
pop	si
ret
.define _raw_clear
_raw_clear: 
mov	bx, sp
push	di
les	di, 2(bx)
xor	ax, ax
mov	cx, 6(bx)
shr	cx, #1
jb	byteclear
rep
stow
j cleardone
byteclear: 
rcl	cx, #1
rep
stob
cleardone: 
mov	ax, ds
mov	es, ax
pop	di
ret
.define _get_word, _put_word
_get_word: 
mov	bx, sp
push	ds
lds	bx, 2(bx)
mov	ax, (bx)
pop	ds
ret
_put_word: 
mov	bx, sp
push	ds
mov	ax, 6(bx)
lds	bx, 2(bx)
mov	(bx), ax
pop	ds
ret
.define _relocate
_relocate: 
pop	bx
mov	ax, cs
sub	ax, _cseg
mov	dx, ds
sub	dx, ax
mov	ds, dx
mov	es, dx
mov	ss, dx
mov	_dseg, dx
push	_cseg
push	bx
reti
.data
.align	2
break: .word 	_end
.text
.define _brk, __brk, _sbrk, __sbrk
_brk: 
__brk: 
xor	ax, ax
j sbrk
_sbrk: 
__sbrk: 
mov	ax, break
sbrk: push	ax
mov	bx, sp
add	ax, 4(bx)
mov	break, ax
lea	dx, -1024(bx)
cmp	dx, ax
jb	heaperr
lea	dx, -4096(bx)
cmp	dx, ax
jae	plenty
mov	ax, #memwarn
push	ax
call	_printk
pop	ax
movb	memwarn, #0
plenty: pop	ax
ret
heaperr: mov	ax, #chmem
push	ax
mov	ax, #nomem
push	ax
call	_printk
call	_reboot
.data
nomem: .asciz	"\nOut of%s"
memwarn: .ascii	"\nLow on"
chmem: .asciz	" memory, use chmem to increase the heap\n"
.text
.define _dev_geometry
_dev_geometry: 
movb	dl, _device
cmpb	dl, #0x80
jae	winchester
floppy: 
int	0x11
testb	al, #0x01
jz	geoerr
shl	ax, #1
shl	ax, #1
andb	ah, #0x03
cmpb	dl, ah
ja	geoerr
movb	dh, #2
movb	_heads, dh
mov	bx, #_dskpars
movb	cl, SECTORS(bx)
movb	_sectors, cl
xor	ax, ax
mov	es, ax
seg es
mov	DSKBASE+0, bx
seg es
mov	DSKBASE+2, ds
j geoboth
winchester: 
movb	ah, #0x08
int	0x13
jb	geoerr
andb	cl, #0x3F
movb	_sectors, cl
incb	dh
movb	_heads, dh
geoboth: 
mov	ax, #1
push	ax
movb	al, cl
mulb	dh
mov	secspcyl, ax
geodone: push	ds
pop	es
pop	ax
ret
geoerr: xor	ax, ax
push	ax
j geodone
.bss
secspcyl: .zerow 1
.text
.define _readsectors, _writesectors
_writesectors: 
push	bp
mov	bp, sp
movb	13(bp), #3
j rwsec
_readsectors: 
push	bp
mov	bp, sp
movb	13(bp), #2
rwsec: push	di
push	es
les	bx, 4(bp)
mov	di, #3
cmpb	_device, #0x80
jb	nohd
mov	di, #1
nohd: cmpb	12(bp), #0
jz	done
more: mov	ax, 8(bp)
mov	dx, 10(bp)
div	secspcyl
xchg	ax, dx
movb	ch, dl
divb	_sectors
xorb	dl, dl
shr	dx, #1
shr	dx, #1
orb	dl, ah
movb	cl, dl
incb	cl
movb	dh, al
movb	dl, _device
movb	al, _sectors
subb	al, ah
cmpb	al, 12(bp)
jbe	doit
movb	al, 12(bp)
doit: movb	ah, 13(bp)
push	ax
int	0x13
pop	cx
jb	ioerr
movb	al, cl
addb	bh, al
addb	bh, al
add	8(bp), ax
adc	10(bp), #0
subb	12(bp), al
jnz	more
done: call	wheel
xorb	ah, ah
j finish
ioerr: dec	di
jl	finish
xorb	ah, ah
int	0x13
jae	more
finish: movb	al, ah
xorb	ah, ah
pop	es
pop	di
pop	bp
ret
.define _getchar, _peekchar
_peekchar: 
movb	ah, #1
int	0x16
jnz	getc
xor	ax, ax
ret
_getchar: 
movb	ah, #0
int	0x16
getc: cmpb	al, #0x3D
jnz	noeq
movb	_eqscancode, ah
noeq: cmpb	al, #0x0D
jnz	nocr
movb	al, #0x0A
nocr: xorb	ah, ah
ret
.define _putchar, _putc, _putk
_putchar: 
_putc: 
_putk: mov	bx, sp
movb	al, 2(bx)
testb	al, al
jz	nulch
cmpb	al, #0x0A
jnz	putc
cmpb	wdirty, #0
jz	nodirt
movb	al, #0x20
call	putc
nodirt: movb	al, #0x0D
call	putc
movb	al, #0x0A
putc: movb	ah, #14
mov	bx, #0x0001
int	0x10
movb	wdirty, #0
nulch: ret
wheel: push	si
mov	si, gp
lodb
call	putc
movb	al, #0x08
call	putc
cmp	si, #glyphs+4
jne	wmore
mov	si, #glyphs
wmore: mov	gp, si
incb	wdirty
pop	si
ret
.data
.align	2
gp: .word 	glyphs
glyphs: .ascii	"|/-\\"
wdirty: .byte 	0
.text
.define _reset_video, _set_cursor
_reset_video: 
mov	bx, sp
movb	al, #7
cmp	2(bx), #0
jz	clear
movb	al, #3
clear: xorb	ah, ah
int	0x10
xor	dx, dx
j setcur
_set_cursor: 
mov	bx, sp
movb	dl, 2(bx)
movb	dh, 4(bx)
setcur: xorb	bh, bh
movb	ah, #0x02
int	0x10
ret
.define _get_tick
_get_tick: 
xorb	ah, ah
int	0x1A
mov	ax, dx
mov	dx, cx
ret
.define 	_get_video
.define 	_get_ext_memsize
.define 	_get_low_memsize
.define 	_get_processor
_get_video: 
mov	ax, #0x1A00
int	0x10
cmpb	al, #0x1A
jnz	no_dc
mov	ax, #2
cmpb	bl, #5
jz	got_video
inc	ax
cmpb	bl, #4
jz	got_video
inc	ax
cmpb	bl, #7
jz	got_video
inc	ax
cmpb	bl, #8
jz	got_video
no_dc: movb	ah, #0x12
movb	bl, #0x10
int	0x10
cmpb	bl, #0x10
jz	no_ega
mov	ax, #2
cmpb	bh, #1
jz	got_video
inc	ax
j got_video
no_ega: int	0x11
and	ax, #0x30
sub	ax, #0x30
jz	got_video
mov	ax, #1
got_video: 
ret
_get_ext_memsize: 
call	_get_processor
cmp	ax, #186
jbe	no_ext
movb	ah, #0x88
clc
int	0x15
jnb	got_ext_memsize
no_ext: sub	ax, ax
got_ext_memsize: 
ret
_get_low_memsize: 
int	0x12
ret
o32 = 0x66
_get_processor: 
push	bp
mov	bp, sp
push	sp
pop	ax
cmp	ax, sp
jz	new_processor
mov	cx, #0x0120
shlb	ch, cl
mov	ax, #86
jz	got_processor
mov	ax, #186
j got_processor
new_processor: 
sub	sp, #6
.byte 	0x0F
add	-6(bp), ax
cmpb	-1(bp), #0
mov	ax, #286
jnz	got_processor
and	sp, #0xFFFC
.byte 	o32
pushf
pop	ax
pop	dx
mov	bx, ax
mov	cx, dx
xor	dx, #0x0004
push	dx
push	ax
.byte 	o32
popf
.byte 	o32
pushf
pop	ax
pop	dx
push	cx
push	bx
.byte 	o32
popf
xor	dx, cx
test	dx, #0x0004
mov	ax, #386
jz	got_processor
mov	ax, #486
got_processor: 
mov	sp, bp
pop	bp
ret
.define _bootstrap
_bootstrap: 
mov	bx, sp
movb	dl, 2(bx)
lds	si, 4(bx)
xor	ax, ax
mov	es, ax
mov	di, #BUFFER
mov	cx, #PENTRYSIZE
rep
movb
mov	si, #BUFFER
mov	ds, ax
cli
mov	ss, ax
mov	sp, #BOOTOFF
sti
jmpi BOOTOFF, 0
stop_motor: 
mov	dx, #0x03F2
movb	al, #0x0C
out
ret
.define _minix86
_minix86: 
call	stop_motor
mov	bp, sp
mov	ax, #0x100
mov	si, 6(bp)
mov	di, ds
mov	cx, 8(bp)
push	cx
push	si
mov	ds, 4(bp)
mov	es, 4(bp)
cli
mov	(bp), #0
jmpi @(bp)
.define _minix386
_minix386: 
call	stop_motor
mov	bp, sp
mov	di, ds
mov	si, #gdt
mov	bx, #gdt_desc
call	set_base
mov	di, 4(bp)
xor	si, si
mov	bx, #ds_desc
call	set_base
mov	di, ss
xor	si, si
mov	bx, #ss_desc
call	set_base
mov	di, 2(bp)
xor	si, si
mov	bx, #cs_desc
call	set_base
xor	ax, ax
push	ax
push	8(bp)
push	ax
push	6(bp)
mov	si, #gdt
xor	bx, bx
movb	ah, #0x89
cli
pushf
push	2(bp)
push	bx
mov	ds, bx
jmpi @4*0x15
set_base: 
mov	2(bx), di
mov	cx, #4
seg2abs: 
shl	2(bx), #1
rclb	4(bx), #1
loop	seg2abs
add	2(bx), si
adcb	4(bx), #0
ret
.data
.align	2
UNSET	= 0
gdt: 
null_desc: 
.word 	0x0000, 0x0000
.byte 	0x00, 0x00, 0x00, 0x00
gdt_desc: 
.word 	8*8-1, UNSET
.byte 	UNSET, 0x00, 0x00, 0x00
idt_desc: 
.word 	0x0000, 0x0000
.byte 	0x00, 0x00, 0x00, 0x00
ds_desc: 
.word 	0xFFFF, UNSET
.byte 	UNSET, 0x92, 0xCF, 0x00
es_desc: 
.word 	0xFFFF, 0x0000
.byte 	0x00, 0x92, 0xCF, 0x00
ss_desc: 
.word 	0xFFFF, UNSET
.byte 	UNSET, 0x92, 0x40, 0x00
cs_desc: 
.word 	0xFFFF, UNSET
.byte 	UNSET, 0x9A, 0xCF, 0x00
bios_desc: 
.word 	UNSET, UNSET
.byte 	UNSET, UNSET, UNSET, UNSET
