( ----- 000 )
: C>!, BX 0 MOVxI, BL 0 ADCi,
8086 MASTER INDEX

301 8086 boot code             306 8086 HAL
311 8086 assembler             320 8086 drivers
( ----- 001 )
\ 8086 macros
: 8086A 5 LOAD ( wordtbl ) 311 318 LOADR 7 LOAD ( Flow ) ;
: 8086C 302 309 LOADR ;
( ----- 002 )
\ 8086 boot code. PS=SP, RS=BP, IP=DX, TOS=BX
FJR JRi, TO L1 ( main ) \ 03=boot driveno
10 ALLOT0 \ End of Stable ABI
L1 FMARK ( main ) DX POPx, ( boot drive no ) $03 DL MOVmr,
 SP PS_ADDR MOVxI, BP RS_ADDR MOVxI,
 DI $04 ( BOOT ) MOVxm, DI JMPr,
LSET lblval DI POPx, BX PUSHx, BX [DI] x[] MOV[], \ to next
LSET lblnext DI DX MOVxx, ( <-- IP ) DX INCx, DX INCx,
 DI [DI] x[] MOV[], DI JMPr,
LSET lblcell AX POPx, BX PUSHx, BX AX MOVxx, lblnext BR JRi,
LSET lblxt BP INCx, BP INCx, [BP] 0 DX []+x MOV[], ( pushRS )
 DX POPx, lblnext BR JRi,
LSET lbldoes DI POPx, BX PUSHx, BX DI MOVxx,  BX INCx, BX INCx,
 DI [DI] x[] MOV[], DI JMPr,
( ----- 003 )
CODE EXIT DX [BP] 0 x[]+ MOV[], BP DECx, BP DECx, ;CODE
CODE []= ( a1 a2 u -- f ) CX BX MOVxx, SI POPx, DI POPx,
 CLD, REPZ, CMPSB, BX 0 MOVxI, IFZ, BX INCx, THEN, ;CODE
CODE [C]? ( c a u -- i ) CX BX MOVxx, DI POPx, AX POPx,
 CLD, REPNZ, SCASB, IFNZ, CX BX MOVxx, THEN,
 BX CX SUBxx, BX DECx, ;CODE
CODE QUIT LSET L1 ( used in ABORT )
 BP RS_ADDR MOVxI, DI $0a ( main ) MOVxm, DI JMPr,
CODE ABORT SP PS_ADDR MOVxI, L1 BR JRi,
CODE BYE HLT, BEGIN, BR JRi,
( ----- 004 )
CODE FIND ( sa sl -- w? f ) CX BX MOVxx, SI POPx,
 DI SYSVARS $2 ( CURRENT ) + MOVxm,
 BEGIN, ( loop )
   AL [DI] -1 r[]+ MOV[], $7f ANDALi, ( strlen )
   CL AL CMPrr, IFZ, ( same len )
     SI PUSHx, DI PUSHx, CX PUSHx, ( --> )
       3 ADDALi, ( header ) AH AH XORrr, DI AX SUBxx,
       CLD, REPZ, CMPSB,
     CX POPx, DI POPx, SI POPx, ( <-- )
     IFZ, DI PUSHx, BX 1 MOVxI, ;CODE THEN,
   THEN,
   DI [x] 3 SUB[]i, DI [DI] x[] MOV[], ( prev ) DI DI ORxx,
 BR JRNZi, ( loop ) BX BX XORxx, ;CODE
( ----- 005 )
CODE * AX POPx, DX PUSHx, ( protect from MUL ) BX MULx, DX POPx,
 BX AX MOVxx, ;CODE
CODE /MOD AX POPx, DX PUSHx, ( protect )
 DX DX XORxx, BX DIVx,
 BX DX MOVxx, DX POPx, ( unprotect )
 BX PUSHx, ( modulo ) BX AX MOVxx, ( division ) ;CODE
CODE RCNT
 BX PUSHx, BX BP MOVxx, AX RS_ADDR MOVxI, BX AX SUBxx, ;CODE
CODE SCNT
 AX PS_ADDR MOVxI, AX SP SUBxx, BX PUSHx, BX AX MOVxx, ;CODE
CODE TICKS ( n=100us ) BX PUSHx,
   SI DX MOVxx, ( protect IP )
   AX POPx, BX 100 MOVxI, BX MULx,
   CX DX MOVxx, ( high ) DX AX MOVxx, ( low )
   AX $8600 MOVxI, ( 86h, WAIT ) $15 INT,
   DX SI MOVxx, ( restore IP ) BX POPx, ;CODE
( ----- 006 )
CODE (n)
 BX PUSHx, DI DX MOVxx, BX [DI] x[] MOV[],
 DX INCx, DX INCx, ;CODE
CODE (b)
 BX PUSHx, DI DX MOVxx, BH BH XORrr, BL [DI] r[] MOV[],
 DX INCx, ;CODE
CODE (br) LSET L1 ( used in ?br )
 DI DX MOVxx, AL [DI] r[] MOV[], AH AH XORrr, CBW,
 DX AX ADDxx, ;CODE
CODE (?br)
 BX BX ORxx, BX POPx, L1 BR JRZi, DX INCx, ;CODE
CODE (next)
 [BP] 0 [w]+ DEC[], L1 BR JRNZi,
 BP DECx, BP DECx, DX INCx, ;CODE
( ----- 007 )
CODE + AX POPx, BX AX ADDxx, ;CODE
CODE - AX POPx, AX BX SUBxx, BX AX MOVxx, ;CODE
CODE < AX POPx, CX CX XORxx, AX BX CMPxx, IFC, CX INCx, THEN,
 BX CX MOVxx, ;CODE
CODE 1+ BX INCx, ;CODE
CODE 1- BX DECx, ;CODE
CODE AND AX POPx, BX AX ANDxx, ;CODE
CODE OR AX POPx, BX AX ORxx, ;CODE
CODE XOR AX POPx, BX AX XORxx, ;CODE
CODE NOT BX BX ORxx, BX 0 MOVxI, IFZ, BX INCx, THEN, ;CODE
CODE >> BX SHRx1, ;CODE
CODE << BX SHLx1, ;CODE
CODE >>8 BL BH MOVrr, BH BH XORrr, ;CODE
CODE <<8 BH BL MOVrr, BL BL XORrr, ;CODE
( ----- 008 )
CODE R@ BX PUSHx, BX [BP] 0 x[]+ MOV[], ;CODE
CODE R~ BP DECx, BP DECx, ;CODE
CODE R> BX PUSHx, BX [BP] 0 x[]+ MOV[], BP DECx, BP DECx, ;CODE
CODE >R BP INCx, BP INCx, [BP] 0 BX []+x MOV[], BX POPx, ;CODE
CODE ROT ( a b c -- b c a ) ( BX=c ) CX POPx, ( b ) AX POPx, \ a
 CX PUSHx, BX PUSHx, BX AX MOVxx, ;CODE
CODE ROT> ( a b c -- c a b ) CX POPx, AX POPx,
 BX PUSHx, AX PUSHx, BX CX MOVxx, ;CODE
CODE DUP LSET L1 BX PUSHx, ;CODE
CODE ?DUP AX BX MOVxx, AX AX ORxx, L1 BR JRNZi, ;CODE
CODE OVER ( a b -- a b a )
 AX POPx, AX PUSHx, BX PUSHx, BX AX MOVxx, ;CODE
CODE SWAP AX BX MOVxx, BX POPx, AX PUSHx, ;CODE
CODE DROP BX POPx, ;CODE
CODE EXECUTE AX BX MOVxx, BX POPx, AX JMPr,
( ----- 009 )
CODE C@ DI BX MOVxx, BH BH XORrr, BL [DI] r[] MOV[], ;CODE
CODE @ DI BX MOVxx, BX [DI] x[] MOV[], ;CODE
CODE C! DI BX MOVxx, CX POPx, [DI] CL []r MOV[], BX POPx, ;CODE
CODE ! DI BX MOVxx, CX POPx, [DI] CX []x MOV[], BX POPx, ;CODE
CODE JMPi! ( pc a -- len ) DI BX MOVxx, AX POPx,
 CL $e9 MOVri, LSET L1 [DI] CL []r MOV[],
 CX SYSVARS $4 ( HOME ) + MOVxm, AX CX SUBxx, AX DECx, AX DECx,
 AX DECx, [DI] 1 AX []+x MOV[], BX 3 MOVxI, ;CODE
CODE CALLi! ( pc a -- len ) DI BX MOVxx, AX POPx,
 CL $e8 MOVri, L1 BR JRi,
CODE i>! ( i a -- len ) DI BX MOVxx, AX POPx,
 CX $bb53 MOVxI, ( push bx;mov bx,nn ) [DI] CX []x MOV[],
 [DI] 2 AX []+x MOV[], BX 4 MOVxI, ;CODE
( ----- 011 )
\ 8086 assembler. See doc/asm
28 CONSTS 0 AL 1 CL 2 DL 3 BL
         4 AH 5 CH 6 DH 7 BH
         0 AX 1 CX 2 DX 3 BX
         4 SP 5 BP 6 SI 7 DI
         0 ES 1 CS 2 SS 3 DS
         0 [BX+SI] 1 [BX+DI] 2 [BP+SI] 3 [BP+DI]
         4 [SI] 5 [DI] 6 [BP] 7 [BX]
: <<3 << << << ;
( ----- 012 )
: OP1 DOER C, DOES> C@ C, ;
$c3 OP1 RET,        $fa OP1 CLI,       $fb OP1 STI,
$f4 OP1 HLT,        $fc OP1 CLD,       $fd OP1 STD,
$90 OP1 NOP,        $98 OP1 CBW,
$f3 OP1 REPZ,       $f2 OP1 REPNZ,     $ac OP1 LODSB,
$ad OP1 LODSW,      $a6 OP1 CMPSB,     $a7 OP1 CMPSW,
$a4 OP1 MOVSB,      $a5 OP1 MOVSW,     $ae OP1 SCASB,
$af OP1 SCASW,      $aa OP1 STOSB,     $ab OP1 STOSW,

: OP1r DOER C, DOES> C@ + C, ;
$40 OP1r INCx,      $48 OP1r DECx,
$58 OP1r POPx,      $50 OP1r PUSHx,
( ----- 013 )
: OPr0 ( reg op ) DOER C, C, DOES>
   C@+ C, C@ <<3 OR $c0 OR C, ;
0 $d0 OPr0 ROLr1,   0 $d1 OPr0 ROLx1,  4 $f6 OPr0 MULr,
1 $d0 OPr0 RORr1,   1 $d1 OPr0 RORx1,  4 $f7 OPr0 MULx,
4 $d0 OPr0 SHLr1,   4 $d1 OPr0 SHLx1,  6 $f6 OPr0 DIVr,
5 $d0 OPr0 SHRr1,   5 $d1 OPr0 SHRx1,  6 $f7 OPr0 DIVx,
0 $d2 OPr0 ROLrCL,  0 $d3 OPr0 ROLxCL, 1 $fe OPr0 DECr,
1 $d2 OPr0 RORrCL,  1 $d3 OPr0 RORxCL, 0 $fe OPr0 INCr,
4 $d2 OPr0 SHLrCL,  4 $d3 OPr0 SHLxCL,
5 $d2 OPr0 SHRrCL,  5 $d3 OPr0 SHRxCL,
( ----- 014 )
: OPrr DOER C, DOES> C@ C, <<3 OR $c0 OR C, ;
$31 OPrr XORxx,     $30 OPrr XORrr,
$88 OPrr MOVrr,     $89 OPrr MOVxx,    $28 OPrr SUBrr,
$29 OPrr SUBxx,     $08 OPrr ORrr,     $09 OPrr ORxx,
$38 OPrr CMPrr,     $39 OPrr CMPxx,    $00 OPrr ADDrr,
$01 OPrr ADDxx,     $12 OPrr ADCrr,    $13 OPrr ADCxx,
$20 OPrr ANDrr,     $21 OPrr ANDxx,
( ----- 015 )
4 WORDTBL mods 'W NOOP 'W C, 'W L, 'W NOOP
: modrm ( disp? modrm -- )
 DUP C, DUP $c7 AND 6 = IF DROP $80 THEN 64 / mods SWAP WEXEC ;
: OP[] ( opbase+modrmbase ) DOER , DOES>
 @ L|M ( disp? modrm opoff modrmbase op ) ROT + C, + modrm ;
( -- disp? modrm opoff )
: [b] ( r/m ) 0 ; : [w] ( r/m ) 1 ;
: [m] ( a ) 6 0 ; : [M] [m] 1+ ;
: [r] ( r ) $c0 OR 0 ; : [x] [r] 1+ ;
: [b]+ ( r/m disp8 ) SWAP $40 OR 0 ; : [w]+ [b]+ 1+ ;
: r[] ( r r/m ) SWAP <<3 OR 2 ; : x[] r[] 1+ ;
: []r ( r/m r ) <<3 OR 0 ; : []x []r 1+ ;
: r[]+ ( r r/m disp8 )
   ROT <<3 ROT OR $40 OR 2 ; : x[]+ r[]+ 1+ ;
: []+r ( r/m disp8 r ) <<3 ROT OR $40 OR 0 ; : []+x []+r 1+ ;
( ----- 016 )
$fe00 OP[] INC[],        $fe08 OP[] DEC[],
$fe30 OP[] PUSH[],       $8e00 OP[] POP[],
$8800 OP[] MOV[],        $3800 OP[] CMP[],

: OP[]i ( opbase+modrmbase ) DOER , DOES> SWAP >R ( i )
 SWAP ( opoff ) DUP IF R@ >>8 NOT IF 2 + THEN THEN >R
 @ L|M ( disp? modrm modrmbase op )
 R@ + C, + modrm R> 1 = IF R> L, ELSE R> C, THEN ;
$8000 OP[]i ADD[]i,      $8010 OP[]i ADC[]i,
$8038 OP[]i CMP[]i,      $8028 OP[]i SUB[]i,

: OPI DOER C, DOES> C@ C, L, ;
$05 OPI ADDAXI,     $15 OPI ADCALI,    $25 OPI ANDAXI,
$2d OPI SUBAXI,     $a1 OPI MOVAXm,    $a3 OPI MOVmAX,
( ----- 017 )
: OPi DOER C, DOES> C@ C, C, ;
$04 OPi ADDALi,     $14 OPi ADCALi,    $24 OPi ANDALi,
$2c OPi SUBALi,     $cd OPi INT,
$eb OPi JRi,        $74 OPi JRZi,
$75 OPi JRNZi,      $72 OPi JRCi,      $73 OPi JRNCi,
$a0 OPi MOVALm,     $a2 OPi MOVmAL,
: MOVri, SWAP $b0 OR C, C, ; : MOVxI, SWAP $b8 OR C, L, ;
: MOVsx, $8e C, SWAP <<3 OR $c0 OR C, ;
: MOVrm, $8a C, SWAP <<3 $6 OR C, L, ;
: MOVxm, $8b C, SWAP <<3 $6 OR C, L, ;
: MOVmr, $88 C, <<3 $6 OR C, L, ;
: MOVmx, $89 C, <<3 $6 OR C, L, ;
: PUSHs, <<3 $06 OR C, ; : POPs, <<3 $07 OR C, ;
: JMPr, $ff C, 7 AND $e0 OR C, ;
: JMPf, ( seg off ) $ea C, L, L, ;
( ----- 018 )
: JMPi, $e9 C, ( jmp near ) PC - 2 - L, ;
: CALLi, $e8 C, ( jmp near ) PC - 2 - L, ;
: i>, BX PUSHx, BX SWAP MOVxI, ;
: JMP(i), MOVAXm, AX JMPr, ;
: (i)>, BX PUSHx, BX SWAP MOVxm, ;
( ----- 020 )
( PC/AT drivers. Load range: 320-326 )
CODE (key?)
 BX PUSHx, BX BX XORxx, AH 1 MOVri, $16 INT, IFNZ,
   AH AH XORrr, $16 INT, AH AH XORrr, BX INCx, AX PUSHx, THEN,
;CODE
( ----- 021 )
CODE 13H08H ( driveno -- cx dx )
 DX PUSHx, ( protect ) DX BX MOVxx, AX $800 MOVxI,
 ES PUSHs, DI DI XORxx, ES DI MOVsx,
 $13 INT, BX DX MOVxx, ES POPs, DX POPx, ( unprotect )
 CX PUSHx, ;CODE
CODE 13H ( ax bx cx dx -- ax bx cx dx )
 SI BX MOVxx, ( DX ) CX POPx, BX POPx, AX POPx,
 DX PUSHx, ( protect ) DX SI MOVxx, DI DI XORxx,
 $13 INT, SI DX MOVxx, DX POPx, ( unprotect )
 AX PUSHx, BX PUSHx, CX PUSHx, BX SI MOVxx, ;CODE
( ----- 022 )
DRV_ADDR CONSTANT FDSPT
DRV_ADDR 1+ CONSTANT FDHEADS
:~ ( 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 ROT OR 1+ ( AX BX head CX )
 SWAP <<8 $03 C@ ( boot drive ) OR ( AX BX CX DX )
 13H 2DROP 2DROP ;
( ----- 023 )
\ Sectors are 512b, so blk numbers are all x2. We add 16 to
\ this because blkfs starts at sector 16.
: FD@ ( blkno blk( -- )
 SWAP << ( 2* ) 16 + 2DUP ( a b a b )
 $0201 ROT> ( a b c a b ) ~ ( a b )
 1+ SWAP $200 + SWAP $0201 ROT> ( c a b ) ~ ;
: FD! ( blkno blk( -- )
 SWAP << ( 2* ) 16 + 2DUP ( a b a b )
 $0301 ROT> ( a b c a b ) ~ ( a b )
 1+ SWAP $200 + SWAP $0301 ROT> ( c a b ) ~ ;
: FD$
\ get number of sectors per track with command 08H.
 $03 ( boot drive ) C@ 13H08H
 >>8 1+ FDHEADS C!
 $3f AND FDSPT C! ;
( ----- 024 )
2 CONSTS 80 COLS 25 LINES
CODE CURSOR! ( new old ) AX POPx, ( new ) DX PUSHx, ( protect )
 BX 80 MOVxI, DX DX XORxx, BX DIVx, ( col in DL, row in AL )
 DH AL MOVrr, AH 2 MOVri,
 $10 INT, DX POPx, ( unprotect ) BX POPx, ;CODE
CODE _ ( c -- ) \ char out
 AL BL MOVrr, BX POPx, AH $0e MOVri, $10 INT, ;CODE
: CELL! ( c pos -- ) 0 CURSOR! _ ;
: NEWLN ( old -- new ) 1+ DUP LINES = IF 1- CR ~ LF ~ THEN ;