( ----- 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 ;