commit 72a6f120e181b8ee1ec55ee1777d0fd0a180d378
parent f6de9c233e94c5de6510c1ea2dc76904c9729fbe
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Thu, 2 Jun 2022 13:49:07 -0400
cc: liftoff! (add asm.fs)
We closed the loop by adding a rudimentary asm.fs to support code generation
from cc1.fs. This means that we can compile C code into executable words right
from the system.
You can see an example in testcc.fs
Diffstat:
A | fs/asm.fs | | | 60 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | testasm.fs | | | 10 | ++++++++++ |
2 files changed, 70 insertions(+), 0 deletions(-)
diff --git a/fs/asm.fs b/fs/asm.fs
@@ -0,0 +1,60 @@
+\ i386 assembler
+\ This assembler is far far from complete. Only operations needed by the C
+\ compiler are implemented.
+\ This assembler implies that the code will run in protected mode with the D
+\ attribute set.
+
+\ MOD/RM constants
+0 value AX
+1 value CX
+2 value DX
+3 value BX
+4 value SP
+5 value BP
+6 value SI
+7 value DI
+8 value MEM
+9 value IMM
+
+\ Variables
+-1 value tgt \ target register. bit 31 is set if in indirect mode.
+-1 value src \ source register. bit 31 is set for indirect mode.
+-1 value disp \ displacement to use
+\ tgt and src are values from constants above.
+\ bits 8-9 represent the appropriate mod (from modrm) for this tgt/src
+\ bit 10 is for 16bit mode. -1 means unset.
+: asm$ -1 to tgt -1 to src -1 to disp ;
+: _err abort" argument error" ;
+
+\ addressing modes
+: tgt? tgt 0>= ;
+: src? src 0>= ;
+: disp? disp 0>= ;
+: _id dup 0< if _err then $1f and ;
+: tgtid tgt _id ;
+: srcid tgt _id ;
+: mod ( tgt-or-src -- mod ) >> >> $c0 and ;
+: is16? ( tgt-or-src -- f ) 10 rshift 1 and ;
+: isimm? ( tgt-or-src -- f ) _id IMM = ;
+
+: tgt-or-src! tgt 0< if to tgt else to src then ;
+: r! ( reg -- ) $700 or ( mod 3 + 32 ) tgt-or-src! ;
+: [r]! ( reg -- ) $500 or ( mod 1 + 32 ) tgt-or-src! ;
+
+: eax AX r! ;
+: ebp BP r! ;
+: [ebp] BP [r]! 0 to disp ;
+: i32 IMM $400 or to src ;
+
+\ Writing the thing
+: prefix, ( -- ) exit
+ tgt is16? if $66 c, then src dup isimm? not swap is16? and if $67 c, then ;
+: inh, ( op -- ) c, asm$ ;
+: modrm, ( imm? op -- )
+ prefix, c, tgtid tgt mod or ( modrm ) src isimm?
+ if $28 or ( 5 in reg ) c, , else c, then disp? if disp c, then asm$ ;
+
+\ operations
+: mov, src isimm? if prefix, $b8 tgtid or c, , asm$ else $89 modrm, then ;
+: sub, $81 modrm, ;
+: ret, $c3 inh, ;
diff --git a/testasm.fs b/testasm.fs
@@ -0,0 +1,10 @@
+\ ./dusk < testasm.fs
+f<< asm.fs
+: spit ( a u -- ) >r >A begin Ac@+ .x1 spc> next ;
+here
+eax 42 i32 mov,
+ebp 4 i32 sub,
+[ebp] eax mov,
+ret,
+here over - spit
+bye