Compare commits

...

3 Commits

Author SHA1 Message Date
Virgil Dupras 94ed01086a pcat: move drivers and xcomp to blkfs 2020-06-22 14:21:25 -04:00
Virgil Dupras 1bea45acb8 8086a: add PUSHs, and POPs, 2020-06-22 13:54:33 -04:00
Virgil Dupras 06d997f26a pcat: write recipe README 2020-06-22 13:34:20 -04:00
38 changed files with 341 additions and 278 deletions

View File

@ -10,7 +10,7 @@ MASTER INDEX
550 TI-84+ Recipe 580 RC2014 Recipe
620 Sega Master System Recipe
650 AVR assembler 730 8086 assembler
810 PC/AT Recipe
800 8086 boot code 830 PC/AT recipe

View File

@ -5,6 +5,7 @@
: MOVxm, 0x8b A, SWAP <<3 0x6 OR A, A,, ;
: MOVmr, 0x88 A, <<3 0x6 OR A, A,, ;
: MOVmx, 0x89 A, <<3 0x6 OR A, A,, ;
: PUSHs, <<3 0x06 OR A, ; : POPs, <<3 0x07 OR A, ;
: SUBxi, 0x83 A, SWAP 0xe8 OR A, A, ;
: ADDxi, 0x83 A, SWAP 0xc0 OR A, A, ;
: JMPr, 0xff A, 7 AND 0xe0 OR A, ;

16
blk/800 Normal file
View File

@ -0,0 +1,16 @@
8086 boot code
Code in the following blocks assemble into a binary that is
suitable to plug into Core words (B350) to achieve a fully
functional Collapse OS. It is structured in a way that is
very similar to Z80 boot code (B280) and requires the same
constants to be pre-declared.
RESERVED REGISTERS: SP is reserved for PSP, BP is for RSP and
DX is for IP. Whenever you use these registers for another
purpose, be sure to protect their initial value. Like with
Z80, you can use SP freely in native code, but you have to make
sure it goes back to its previous level before next is called.
(cont.)

13
blk/801 Normal file
View File

@ -0,0 +1,13 @@
STABLE ABI: As a compatible binary, this binary follows the
same stable ABI as its z80 counterpart.
PS CHECKS: Unlike z80 boot code, we don't check PS at each next
call (we do check RS though). It is the responsibility of every
native PSP-modifying word to call chkPS, . Also, chkPS, is a
bit different than in z80: it is parametrizable. The idea is
that we always call chkPS, before popping, telling the expected
size of stack. This allows for some interesting optimization.
For example, in SWAP, no need to pop, chkPS, then push, we can
chkPS and then proceed to optimized swapping in PS.
To assemble, load blocks 805 through 820.

15
blk/805 Normal file
View File

@ -0,0 +1,15 @@
VARIABLE lblexec VARIABLE lblnext
H@ ORG !
JMPn, 0 A,, ( 00, main ) 0 A, ( 03, boot driveno )
0 A,, ( 04, BOOT )
0 A,, ( 06, uflw ) 0 A,, ( 08, LATEST )
0 A, 0 A, 0 A,, ( unused )
0 A, 0 A,, ( unused ) JMPn, 0 A,, ( 11, pushRS )
JMPn, 0 A,, ( 14, popRS ) 0 A, 0 A,, ( unused )
JMPn, 0 A,, ( 1a, next ) 0 A, 0 A,, ( unused )
0 A, 0 A, 0 A, 0 A, ( unused )
0 A, 0 A, 0 A, 0 A, ( unused )
0 A, 0 A,, ( unused )
0 A, 0 A,, 0 A, 0 A, ( unused )
0 A, 0 A,, ( unused )
JMPn, 0 A,, ( 33, execute ) 0 A, 0 A, 0 A, 0 A,, ( unused )

16
blk/806 Normal file
View File

@ -0,0 +1,16 @@
( BOOT DICT: There are only 3 words in the boot dict, but
these words' offset need to be stable, so they're part of
the "stable ABI" )
'E' A, 'X' A, 'I' A, 'T' A, 0 A,, ( prev ) 4 A, ( len )
H@ XCURRENT ! ( set current tip of dict, 0x42 )
0 A, ( native )
DX [BP] 0 MOVx[]+, BP DECx, BP DECx, ( popRS )
;CODE NOP,
CODE (br) ( 0x53 ) L2 BSET ( used in br? )
DI DX MOVxx, DI [DI] MOVx[], DX DI ADDxx,
;CODE NOP, NOP,
CODE (?br) ( 0x67 )
AX POPx, AX AX ORxx, JZ, L2 @ RPCs, ( False, branch )
( True, skip next 2 bytes and don't branch )
L1 BSET ( loop will jump here ) DX INCx, DX INCx,
;CODE NOP, NOP, NOP, NOP, NOP,

15
blk/807 Normal file
View File

@ -0,0 +1,15 @@
CODE (loop) ( 0x80 )
[BP] 0 INC[w]+, ( I++ )
( Jump if I <> I' )
AX [BP] 0 MOVx[]+, AX [BP] -2 CMPx[]+,
JNZ, L2 @ RPCs, ( branch )
( don't branch )
BP 4 SUBxi, JMPs, L1 @ RPCs,
ORG @ 0xa3 + HERE !
CODE 2>R ( 0xa9 )
[BP] 4 POP[w]+, [BP] 2 POP[w]+, BP 4 ADDxi,
;CODE NOP, NOP, NOP, NOP, NOP,
CODE (n) ( 0xbf, number literal )
DI DX MOVxx, DI [DI] MOVx[], DI PUSHx,
DX INCx, DX INCx,
;CODE NOP, NOP,

6
blk/808 Normal file
View File

@ -0,0 +1,6 @@
CODE (s) ( 0xd4, string literal, see B287 )
DI DX MOVxx, ( IP )
AH AH XORrr, AL [DI] MOVr[], ( slen )
DX PUSHx, DX INCx, DX AX ADDxx,
;CODE
( END OF STABLE ABI )

9
blk/809 Normal file
View File

@ -0,0 +1,9 @@
lblnext BSET PC 0x1d - ORG @ 0x1b + ! ( next )
( RSP check )
AX RS_ADDR MOVxI, BP AX CMPxx,
IFC, ( BP < RS_ADDR )
DI 0x06 MOVxm, JMPs, L1 FWRs ( execute )
THEN,
DI DX MOVxx, ( <-- IP ) DX INCx, DX INCx,
DI [DI] MOVx[], ( wordref )
( continue to execute ) L1 FSET

29
blk/810
View File

@ -1,16 +1,15 @@
PC/AT Recipe
lblexec BSET PC 0x36 - ORG @ 0x34 + ! ( DI -> wordref )
AL [DI] MOVr[], DI INCx, ( PFA )
AL AL ORrr, IFZ, DI JMPr, THEN, ( native )
AL DECr, IFNZ, ( cell or does )
DI PUSHx, ( push PFA )
AL DECr, IFZ, ( cell ) JMPs, lblnext @ RPCs, THEN,
( does, see B302 )
DI INCx, DI INCx, DI [DI] MOVx[],
THEN, ( continue to compiled )
( compiled )
BP INCx, BP INCx, [BP] 0 DX MOV[]+x, ( pushRS )
DX DI MOVxx, DX INCx, DX INCx, ( --> IP )
DI [DI] MOVx[],
JMPs, lblexec @ RPCs,
Work in progress.
Register usage: SP is PSP, BP is RSP, DX is IP
Unlike z80 boot code, we don't check PS at each next call (we
do check RS though). It is the responsibility of every native
PSP-modifying word to call chkPS, . Also, chkPS, is a bit
different than in z80: it is parametrizable. The idea is that
we always call chkPS, before popping, telling the expected size
of stack. This allows for some interesting optimization. For
example, in SWAP, no need to pop, chkPS, then push, we can
chkPS and then proceed to optimized swapping in PS.
811 MBR bootloader 812-829 Boot code

17
blk/811
View File

@ -1,12 +1,5 @@
H@ ORG ! 0x7c00 BIN( ! ( BIOS loads boot bin at 0x7c00 )
JMPs, L1 FWRs ( start )
ORG @ 0x25 + HERE ! ( bypass BPB )
L1 FSET ( start )
CLI, CLD, AX 0x800 MOVxI, DS AX MOVsx, ES AX MOVsx,
SS AX MOVsx, DX PUSHx, ( will be popped by OS ) STI,
AH 2 MOVri, DH 0 MOVri, CH 0 MOVri, CL 2 MOVri, AL 15 MOVri,
BX 0 MOVxI, 0x13 INT, ( read sectors 2-15 of boot floppy )
( TODO: reading 12 sectors like this probably doesn't work
on real vintage PC/AT with floppy. Make this more robust. )
0x800 0 JMPf,
ORG @ 0x1fe + HERE ! 0x55 A, 0xaa A,
lblchkPS BSET ( CX -> expected size )
AX PS_ADDR MOVxI, AX SP SUBxx, 2 SUBAXI, ( CALL adjust )
AX CX CMPxx,
IFNC, ( we're good ) RETn, THEN,
( underflow ) DI 0x06 MOVxm, JMPs, lblexec @ RPCs,

24
blk/812
View File

@ -1,15 +1,9 @@
VARIABLE lblexec VARIABLE lblnext
H@ ORG !
JMPn, 0 A,, ( 00, main ) 0 A, ( 03, boot driveno )
0 A,, ( 04, BOOT )
0 A,, ( 06, uflw ) 0 A,, ( 08, LATEST )
0 A, 0 A, 0 A,, ( unused )
0 A, 0 A,, ( unused ) JMPn, 0 A,, ( 11, pushRS )
JMPn, 0 A,, ( 14, popRS ) 0 A, 0 A,, ( unused )
JMPn, 0 A,, ( 1a, next ) 0 A, 0 A,, ( unused )
0 A, 0 A, 0 A, 0 A, ( unused )
0 A, 0 A, 0 A, 0 A, ( unused )
0 A, 0 A,, ( unused )
0 A, 0 A,, 0 A, 0 A, ( unused )
0 A, 0 A,, ( unused )
JMPn, 0 A,, ( 33, execute ) 0 A, 0 A, 0 A, 0 A,, ( unused )
PC 3 - ORG @ 1+ ! ( main )
DX POPx, ( boot drive no ) 0x03 DL MOVmr,
SP PS_ADDR MOVxI, BP RS_ADDR MOVxI,
DI 0x08 MOVxm, ( LATEST )
( HERE begins at CURRENT )
RAMSTART 0x4 ( HERE ) + DI MOVmx,
RAMSTART 0x2 ( CURRENT ) + DI MOVmx,
DI 0x04 ( BOOT ) MOVxm,
JMPn, lblexec @ RPCn, ( execute )

32
blk/813
View File

@ -1,16 +1,16 @@
( BOOT DICT: There are only 3 words in the boot dict, but
these words' offset need to be stable, so they're part of
the "stable ABI" )
'E' A, 'X' A, 'I' A, 'T' A, 0 A,, ( prev ) 4 A, ( len )
H@ XCURRENT ! ( set current tip of dict, 0x42 )
0 A, ( native )
DX [BP] 0 MOVx[]+, BP DECx, BP DECx, ( popRS )
;CODE NOP,
CODE (br) ( 0x53 ) L2 BSET ( used in br? )
DI DX MOVxx, DI [DI] MOVx[], DX DI ADDxx,
;CODE NOP, NOP,
CODE (?br) ( 0x67 )
AX POPx, AX AX ORxx, JZ, L2 @ RPCs, ( False, branch )
( True, skip next 2 bytes and don't branch )
L1 BSET ( loop will jump here ) DX INCx, DX INCx,
;CODE NOP, NOP, NOP, NOP, NOP,
( native words )
CODE EXECUTE 1 chkPS,
DI POPx, JMPn, lblexec @ RPCn,
CODE >R 1 chkPS,
BP INCx, BP INCx, [BP] 0 POP[w]+,
;CODE NOP, NOP, NOP,
CODE R>
[BP] 0 PUSH[w]+, BP DECx, BP DECx,
;CODE
CODE 2R> 2 chkPS,
[BP] -2 PUSH[w]+, [BP] 0 PUSH[w]+, BP 4 SUBxi,
;CODE
CODE ROT ( a b c -- b c a ) 3 chkPS,
CX POPx, BX POPx, AX POPx,
BX PUSHx, CX PUSHx, AX PUSHx,
;CODE

27
blk/814
View File

@ -1,15 +1,12 @@
CODE (loop) ( 0x80 )
[BP] 0 INC[w]+, ( I++ )
( Jump if I <> I' )
AX [BP] 0 MOVx[]+, AX [BP] -2 CMPx[]+,
JNZ, L2 @ RPCs, ( branch )
( don't branch )
BP 4 SUBxi, JMPs, L1 @ RPCs,
ORG @ 0xa3 + HERE !
CODE 2>R ( 0xa9 )
[BP] 4 POP[w]+, [BP] 2 POP[w]+, BP 4 ADDxi,
;CODE NOP, NOP, NOP, NOP, NOP,
CODE (n) ( 0xbf, number literal )
DI DX MOVxx, DI [DI] MOVx[], DI PUSHx,
DX INCx, DX INCx,
;CODE NOP, NOP,
CODE DUP 1 chkPS, AX POPx, AX PUSHx, AX PUSHx, ;CODE
CODE ?DUP 1 chkPS, AX POPx, AX AX ORxx, AX PUSHx,
IFNZ, AX PUSHx, THEN, ;CODE
CODE DROP 1 chkPS, AX POPx, ;CODE
CODE SWAP AX POPx, BX POPx, AX PUSHx, BX PUSHx, ;CODE
CODE OVER ( a b -- a b a ) 2 chkPS,
DI SP MOVxx, AX [DI] 2 MOVx[]+, AX PUSHx, ;CODE
CODE PICK
DI POPx, DI SHLx1, ( x2 )
CX DI MOVxx, CX 2 ADDxi, CALLn, lblchkPS @ RPCn,
DI SP ADDxx, DI [DI] MOVx[], DI PUSHx,
;CODE

20
blk/815
View File

@ -1,6 +1,16 @@
CODE (s) ( 0xd4, string literal, see B287 )
DI DX MOVxx, ( IP )
AH AH XORrr, AL [DI] MOVr[], ( slen )
DX PUSHx, DX INCx, DX AX ADDxx,
CODE (roll) ( "2 3 4 5 4 --> 2 4 5 5". See B311 )
CX POPx, CX 2 ADDxi, CALLn, lblchkPS @ RPCn, CX 2 SUBxi,
SI SP MOVxx, SI CX ADDxx,
DI SI MOVxx, DI 2 ADDxi, STD, REPZ, MOVSB,
;CODE
( END OF STABLE ABI )
CODE 2DROP 2 chkPS, SP 4 ADDxi, ;CODE
CODE 2DUP 2 chkPS,
AX POPx, BX POPx,
BX PUSHx, AX PUSHx, BX PUSHx, AX PUSHx,
;CODE
CODE S0 AX PS_ADDR MOVxI, AX PUSHx, ;CODE
CODE 'S SP PUSHx, ;CODE
CODE AND 2 chkPS,
AX POPx, BX POPx, AX BX ANDxx, AX PUSHx, ;CODE
CODE OR 2 chkPS,
AX POPx, BX POPx, AX BX ORxx, AX PUSHx, ;CODE

24
blk/816
View File

@ -1,9 +1,15 @@
lblnext BSET PC 0x1d - ORG @ 0x1b + ! ( next )
( RSP check )
AX RS_ADDR MOVxI, BP AX CMPxx,
IFC, ( BP < RS_ADDR )
DI 0x06 MOVxm, JMPs, L1 FWRs ( execute )
THEN,
DI DX MOVxx, ( <-- IP ) DX INCx, DX INCx,
DI [DI] MOVx[], ( wordref )
( continue to execute ) L1 FSET
CODE XOR 2 chkPS,
AX POPx, BX POPx, AX BX XORxx, AX PUSHx, ;CODE
CODE NOT 1 chkPS,
AX POPx, AX AX ORxx,
IFNZ, AX -1 MOVxI, THEN, AX INCx, AX PUSHx,
;CODE
CODE + 2 chkPS,
AX POPx, BX POPx, AX BX ADDxx, AX PUSHx, ;CODE
CODE - 2 chkPS,
BX POPx, AX POPx, AX BX SUBxx, AX PUSHx, ;CODE
CODE * 2 chkPS,
AX POPx, BX POPx,
DX PUSHx, ( protect from MUL ) BX MULx, DX POPx,
AX PUSHx,
;CODE

31
blk/817
View File

@ -1,15 +1,16 @@
lblexec BSET PC 0x36 - ORG @ 0x34 + ! ( DI -> wordref )
AL [DI] MOVr[], DI INCx, ( PFA )
AL AL ORrr, IFZ, DI JMPr, THEN, ( native )
AL DECr, IFNZ, ( cell or does )
DI PUSHx, ( push PFA )
AL DECr, IFZ, ( cell ) JMPs, lblnext @ RPCs, THEN,
( does, see B302 )
DI INCx, DI INCx, DI [DI] MOVx[],
THEN, ( continue to compiled )
( compiled )
BP INCx, BP INCx, [BP] 0 DX MOV[]+x, ( pushRS )
DX DI MOVxx, DX INCx, DX INCx, ( --> IP )
DI [DI] MOVx[],
JMPs, lblexec @ RPCs,
CODE /MOD 2 chkPS,
BX POPx, AX POPx, DX PUSHx, ( protect )
DX DX XORxx, BX DIVx,
BX DX MOVxx, DX POPx, ( unprotect )
BX PUSHx, ( modulo ) AX PUSHx, ( division )
;CODE
CODE ! 2 chkPS, DI POPx, AX POPx, [DI] AX MOV[]x, ;CODE
CODE @ 1 chkPS, DI POPx, AX [DI] MOVx[], AX PUSHx, ;CODE
CODE C! 2 chkPS, DI POPx, AX POPx, [DI] AX MOV[]r, ;CODE
CODE C@ 1 chkPS,
DI POPx, AH AH XORrr, AL [DI] MOVr[], AX PUSHx, ;CODE
CODE I [BP] 0 PUSH[w]+, ;CODE
CODE I' [BP] -2 PUSH[w]+, ;CODE
CODE J [BP] -4 PUSH[w]+, ;CODE
CODE (resSP) SP PS_ADDR MOVxI, ;CODE
CODE (resRS) BP RS_ADDR MOVxI, ;CODE

21
blk/818
View File

@ -1,5 +1,16 @@
lblchkPS BSET ( CX -> expected size )
AX PS_ADDR MOVxI, AX SP SUBxx, 2 SUBAXI, ( CALL adjust )
AX CX CMPxx,
IFNC, ( we're good ) RETn, THEN,
( underflow ) DI 0x06 MOVxm, JMPs, lblexec @ RPCs,
CODE BYE BEGIN, JMPs, AGAIN, ;CODE
CODE S= 2 chkPS,
SI POPx, DI POPx, CH CH XORrr, CL [SI] MOVr[],
CL [DI] CMPr[],
IFZ, ( same size? )
SI INCx, DI INCx, CLD, REPZ, CMPSB,
THEN,
PUSHZ,
;CODE
CODE CMP 2 chkPS,
BX POPx, AX POPx, CX CX XORxx, AX BX CMPxx,
IFNZ, ( < or > )
CX INCx, IFC, ( < ) CX DECx, CX DECx, THEN,
THEN,
CX PUSHx,
;CODE

View File

View File

View File

@ -1,9 +0,0 @@
PC 3 - ORG @ 1+ ! ( main )
DX POPx, ( boot drive no ) 0x03 DL MOVmr,
SP PS_ADDR MOVxI, BP RS_ADDR MOVxI,
DI 0x08 MOVxm, ( LATEST )
( HERE begins at CURRENT )
RAMSTART 0x4 ( HERE ) + DI MOVmx,
RAMSTART 0x2 ( CURRENT ) + DI MOVmx,
DI 0x04 ( BOOT ) MOVxm,
JMPn, lblexec @ RPCn, ( execute )

16
blk/822
View File

@ -1,16 +0,0 @@
( native words )
CODE EXECUTE 1 chkPS,
DI POPx, JMPn, lblexec @ RPCn,
CODE >R 1 chkPS,
BP INCx, BP INCx, [BP] 0 POP[w]+,
;CODE NOP, NOP, NOP,
CODE R>
[BP] 0 PUSH[w]+, BP DECx, BP DECx,
;CODE
CODE 2R> 2 chkPS,
[BP] -2 PUSH[w]+, [BP] 0 PUSH[w]+, BP 4 SUBxi,
;CODE
CODE ROT ( a b c -- b c a ) 3 chkPS,
CX POPx, BX POPx, AX POPx,
BX PUSHx, CX PUSHx, AX PUSHx,
;CODE

12
blk/823
View File

@ -1,12 +0,0 @@
CODE DUP 1 chkPS, AX POPx, AX PUSHx, AX PUSHx, ;CODE
CODE ?DUP 1 chkPS, AX POPx, AX AX ORxx, AX PUSHx,
IFNZ, AX PUSHx, THEN, ;CODE
CODE DROP 1 chkPS, AX POPx, ;CODE
CODE SWAP AX POPx, BX POPx, AX PUSHx, BX PUSHx, ;CODE
CODE OVER ( a b -- a b a ) 2 chkPS,
DI SP MOVxx, AX [DI] 2 MOVx[]+, AX PUSHx, ;CODE
CODE PICK
DI POPx, DI SHLx1, ( x2 )
CX DI MOVxx, CX 2 ADDxi, CALLn, lblchkPS @ RPCn,
DI SP ADDxx, DI [DI] MOVx[], DI PUSHx,
;CODE

16
blk/824
View File

@ -1,16 +0,0 @@
CODE (roll) ( "2 3 4 5 4 --> 2 4 5 5". See B311 )
CX POPx, CX 2 ADDxi, CALLn, lblchkPS @ RPCn, CX 2 SUBxi,
SI SP MOVxx, SI CX ADDxx,
DI SI MOVxx, DI 2 ADDxi, STD, REPZ, MOVSB,
;CODE
CODE 2DROP 2 chkPS, SP 4 ADDxi, ;CODE
CODE 2DUP 2 chkPS,
AX POPx, BX POPx,
BX PUSHx, AX PUSHx, BX PUSHx, AX PUSHx,
;CODE
CODE S0 AX PS_ADDR MOVxI, AX PUSHx, ;CODE
CODE 'S SP PUSHx, ;CODE
CODE AND 2 chkPS,
AX POPx, BX POPx, AX BX ANDxx, AX PUSHx, ;CODE
CODE OR 2 chkPS,
AX POPx, BX POPx, AX BX ORxx, AX PUSHx, ;CODE

15
blk/825
View File

@ -1,15 +0,0 @@
CODE XOR 2 chkPS,
AX POPx, BX POPx, AX BX XORxx, AX PUSHx, ;CODE
CODE NOT 1 chkPS,
AX POPx, AX AX ORxx,
IFNZ, AX -1 MOVxI, THEN, AX INCx, AX PUSHx,
;CODE
CODE + 2 chkPS,
AX POPx, BX POPx, AX BX ADDxx, AX PUSHx, ;CODE
CODE - 2 chkPS,
BX POPx, AX POPx, AX BX SUBxx, AX PUSHx, ;CODE
CODE * 2 chkPS,
AX POPx, BX POPx,
DX PUSHx, ( protect from MUL ) BX MULx, DX POPx,
AX PUSHx,
;CODE

16
blk/826
View File

@ -1,16 +0,0 @@
CODE /MOD 2 chkPS,
BX POPx, AX POPx, DX PUSHx, ( protect )
DX DX XORxx, BX DIVx,
BX DX MOVxx, DX POPx, ( unprotect )
BX PUSHx, ( modulo ) AX PUSHx, ( division )
;CODE
CODE ! 2 chkPS, DI POPx, AX POPx, [DI] AX MOV[]x, ;CODE
CODE @ 1 chkPS, DI POPx, AX [DI] MOVx[], AX PUSHx, ;CODE
CODE C! 2 chkPS, DI POPx, AX POPx, [DI] AX MOV[]r, ;CODE
CODE C@ 1 chkPS,
DI POPx, AH AH XORrr, AL [DI] MOVr[], AX PUSHx, ;CODE
CODE I [BP] 0 PUSH[w]+, ;CODE
CODE I' [BP] -2 PUSH[w]+, ;CODE
CODE J [BP] -4 PUSH[w]+, ;CODE
CODE (resSP) SP PS_ADDR MOVxI, ;CODE
CODE (resRS) BP RS_ADDR MOVxI, ;CODE

16
blk/827
View File

@ -1,16 +0,0 @@
CODE BYE BEGIN, JMPs, AGAIN, ;CODE
CODE S= 2 chkPS,
SI POPx, DI POPx, CH CH XORrr, CL [SI] MOVr[],
CL [DI] CMPr[],
IFZ, ( same size? )
SI INCx, DI INCx, CLD, REPZ, CMPSB,
THEN,
PUSHZ,
;CODE
CODE CMP 2 chkPS,
BX POPx, AX POPx, CX CX XORxx, AX BX CMPxx,
IFNZ, ( < or > )
CX INCx, IFC, ( < ) CX DECx, CX DECx, THEN,
THEN,
CX PUSHx,
;CODE

5
blk/830 Normal file
View File

@ -0,0 +1,5 @@
PC/AT recipe
832 MBR bootloader 834 KEY/EMIT drivers
836-838 BLK drivers 840 AT-XY drivers
842 xcomp unit

12
blk/832 Normal file
View File

@ -0,0 +1,12 @@
H@ ORG ! 0x7c00 BIN( ! ( BIOS loads boot bin at 0x7c00 )
JMPs, L1 FWRs ( start )
ORG @ 0x25 + HERE ! ( bypass BPB )
L1 FSET ( start )
CLI, CLD, AX 0x800 MOVxI, DS AX MOVsx, ES AX MOVsx,
SS AX MOVsx, DX PUSHx, ( will be popped by OS ) STI,
AH 2 MOVri, DH 0 MOVri, CH 0 MOVri, CL 2 MOVri, AL 15 MOVri,
BX 0 MOVxI, 0x13 INT, ( read sectors 2-15 of boot floppy )
( TODO: reading 12 sectors like this probably doesn't work
on real vintage PC/AT with floppy. Make this more robust. )
0x800 0 JMPf,
ORG @ 0x1fe + HERE ! 0x55 A, 0xaa A,

6
blk/834 Normal file
View File

@ -0,0 +1,6 @@
CODE (emit) 1 chkPS,
AX POPx, AH 0x0e MOVri, ( print char ) 0x10 INT,
;CODE
CODE (key)
AH AH XORrr, 0x16 INT, AH AH XORrr, AX PUSHx,
;CODE

14
blk/836 Normal file
View File

@ -0,0 +1,14 @@
CODE 13H08H ( driveno -- cx dx )
DI POPx, DX PUSHx, ( protect ) DX DI MOVxx, AX 0x800 MOVxI,
ES PUSHs, DI DI XORxx, ES DI MOVsx,
0x13 INT, DI DX MOVxx, ES POPs, DX POPx, ( unprotect )
CX PUSHx, DI PUSHx,
;CODE
CODE 13H ( ax bx cx dx -- ax bx cx dx )
SI POPx, ( DX ) CX POPx, BX POPx, AX POPx,
DX PUSHx, ( protect ) DX SI MOVxx, DI DI XORxx,
0x13 INT, SI DX MOVxx, DX POPx, ( unprotect )
AX PUSHx, BX PUSHx, CX PUSHx, SI PUSHx,
;CODE
: FDSPT 0x70 RAM+ ;
: FDHEADS 0x71 RAM+ ;

10
blk/837 Normal file
View File

@ -0,0 +1,10 @@
: _ ( AX BX sec )
( AH=read sectors, AL=1 sector, BX=dest,
CH=trackno CL=secno DH=head DL=drive )
FDSPT C@ /MOD ( AX BX sec trk )
FDHEADS C@ /MOD ( AX BX sec head trk )
8 LSHIFT ROT OR 1+ ( AX BX head CX )
SWAP 8 LSHIFT 0x03 C@ ( boot drive ) OR ( AX BX CX DX )
13H 2DROP 2DROP
;

14
blk/838 Normal file
View File

@ -0,0 +1,14 @@
: FD@
2 * 16 + ( blkfs starts at sector 16 )
0x0201 BLK( 2 PICK _
0x0201 BLK( 0x200 + ROT 1+ _ ;
: FD!
2 * 16 + ( blkfs starts at sector 16 )
0x0301 BLK( 2 PICK _
0x0301 BLK( 0x200 + ROT 1+ _ ;
: FD$
( get number of sectors per track with command 08H. )
0x03 ( boot drive ) C@ 13H08H
8 RSHIFT 1+ FDHEADS C!
0x3f AND FDSPT C!
;

8
blk/840 Normal file
View File

@ -0,0 +1,8 @@
: COLS 80 ; : LINES 25 ;
CODE AT-XY ( x y )
( DH=row DL=col BH=page )
AX POPx, BX POPx, DX PUSHx, ( protect )
DH AL MOVrr, DL BL MOVrr, BX BX XORxx, AH 2 MOVri,
0x10 INT, DX POPx, ( unprotect )
;CODE

13
blk/842 Normal file
View File

@ -0,0 +1,13 @@
0xff00 CONSTANT RS_ADDR
0xfffa CONSTANT PS_ADDR
RS_ADDR 0x80 - CONSTANT RAMSTART
750 LOAD ( 8086 asm )
262 LOAD ( xcomp ) 270 LOAD ( xcomp overrides )
805 820 LOADR
353 LOAD ( xcomp core low )
834 LOAD ( KEY/EMIT drivers )
836 838 LOADR ( BLK drivers )
840 LOAD ( AT-XY drivers )
380 LOAD ( xcomp core high )
(entry) _ ( Update LATEST ) PC ORG @ 8 + !
," BLK$ FD$ ' FD@ BLK@* ! ' FD! BLK!* ! " EOT,

View File

@ -1,3 +1,48 @@
# PC/AT recipe
# PC/AT
Work in progress.
PC-compatible machines need no introduction. They are one of the most popular
machines of all time. Collapse OS has a 8086 assembler and has boot code
allowing it to run on a PC/AT-compatible machine, using BIOS interrupts in
real mode. Collapse OS always runs in real mode.
In this recipe, we will compile Collapse OS and write it to a USB drive that
is bootable on a modern PC-compatible machine.
## Gathering parts
* A modern PC-compatible machine that can boot from a USB drive.
* A USB drive
* qemu for emulation
## Build the binary
Running `make` in this folder with yield:
* mbr.bin: a 512 byte binary that goes at the beginning of the disk
* os.bin: 8086 Collapse OS binary
* disk.bin: a concatenation of the above, with `blkfs` appended to it starting at
`0x2000`.
`disk.bin` is what goes on the drive.
This binary has `BLK` and `AT-XY` support, which means you have disk I/Os and
can run `VE`.
## Emulation
You can run the built binary in qemu using `make emul`.
## Running on a modern PC
First, copy `disk.bin` onto your USB drive. For example, on an OpenBSD machine,
it could look like:
doas dd if=disk.bin of=/dev/sd1c
Your USB drive is now BIOS-bootable. Boot your computer and enter your BIOS
setup to make sure that "legacy boot" (non-EFI boot, that is, BIOS boot) is
enabled. Configure your boot device priority to ensure that the USB drive has
a chance to boot.
Reboot, you have Collapse OS. Boot is of course instantaneous (we're not used
to this with modern software...).

View File

@ -1,4 +1,4 @@
750 LOAD
811 LOAD
832 LOAD
ORG @ 256 /MOD 2 PC! 2 PC!
H@ 256 /MOD 2 PC! 2 PC!

View File

@ -1,69 +1,3 @@
0xff00 CONSTANT RS_ADDR
0xfffa CONSTANT PS_ADDR
RS_ADDR 0x80 - CONSTANT RAMSTART
750 LOAD ( 8086 asm )
262 LOAD ( xcomp )
270 LOAD ( xcomp overrides )
812 829 LOADR
353 LOAD ( xcomp core low )
CODE (emit) 1 chkPS,
AX POPx, AH 0x0e MOVri, ( print char ) 0x10 INT,
;CODE
CODE (key)
AH AH XORrr, 0x16 INT, AH AH XORrr, AX PUSHx,
;CODE
CODE 13H08H ( driveno -- cx dx )
DI POPx, DX PUSHx, ( protect ) DX DI MOVxx, AX 0x800 MOVxI,
DI DI XORxx, ES DI MOVsx,
0x13 INT, DI DX MOVxx, DX POPx, ( unprotect )
CX PUSHx, DI PUSHx,
DI 0x800 MOVxI, ES DI MOVsx,
;CODE
CODE 13H ( ax bx cx dx -- ax bx cx dx )
SI POPx, ( DX ) CX POPx, BX POPx, AX POPx,
DX PUSHx, ( protect ) DX SI MOVxx, DI DI XORxx,
0x13 INT, SI DX MOVxx, DX POPx, ( unprotect )
AX PUSHx, BX PUSHx, CX PUSHx, SI PUSHx,
;CODE
: FDSPT 0x70 RAM+ ;
: FDHEADS 0x71 RAM+ ;
: _ ( AX BX sec )
( AH=read sectors, AL=1 sector, BX=dest,
CH=trackno CL=secno DH=head DL=drive )
FDSPT C@ /MOD ( AX BX sec trk )
FDHEADS C@ /MOD ( AX BX sec head trk )
8 LSHIFT ROT OR 1+ ( AX BX head CX )
SWAP 8 LSHIFT 0x03 C@ ( boot drive ) OR ( AX BX CX DX )
13H 2DROP 2DROP
;
: FD@
2 * 16 + ( blkfs starts at sector 16 )
0x0201 BLK( 2 PICK _
0x0201 BLK( 0x200 + ROT 1+ _ ;
: FD!
2 * 16 + ( blkfs starts at sector 16 )
0x0301 BLK( 2 PICK _
0x0301 BLK( 0x200 + ROT 1+ _ ;
: FD$
( get number of sectors per track with command 08H. )
0x03 ( boot drive ) C@ 13H08H
8 RSHIFT 1+ FDHEADS C!
0x3f AND FDSPT C!
;
: COLS 80 ; : LINES 25 ;
CODE AT-XY ( x y )
( DH=row DL=col BH=page )
AX POPx, BX POPx, DX PUSHx, ( protect )
DH AL MOVrr, DL BL MOVrr, BX BX XORxx, AH 2 MOVri,
0x10 INT, DX POPx, ( unprotect )
;CODE
380 LOAD ( xcomp core high )
(entry) _
( Update LATEST )
PC ORG @ 8 + !
," BLK$ FD$ "
," ' FD@ BLK@* ! "
," ' FD! BLK!* ! "
EOT,
842 LOAD ( PC/AT xcomp )
ORG @ 256 /MOD 2 PC! 2 PC!
H@ 256 /MOD 2 PC! 2 PC!