duskos

dusk os fork
git clone git://git.alexwennerberg.com/duskos
Log | Files | Refs | README | LICENSE

commit e6e821d66191046a366dc005416d811743279882
parent e736981c7b65fa1b69905d0e7b162cd43668c3e3
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Sat, 23 Jul 2022 07:30:02 -0400

i386: begin structuring the boot binary

It's getting exciting!

Diffstat:
MREADME.md | 10++++++++++
Mbuildpc.fs | 6+++---
Mfs/asm/i386.fs | 2+-
Mfs/asm/label.fs | 4+++-
Mfs/doc/asm.txt | 11++++++++++-
Mfs/xcomp/i386.fs | 18+++++++++++++-----
Mfs/xcomp/pc/mbr.fs | 15++++++++-------
Afs/xcomp/tools.fs | 23+++++++++++++++++++++++
8 files changed, 71 insertions(+), 18 deletions(-)

diff --git a/README.md b/README.md @@ -195,6 +195,16 @@ and echoed twice. To avoid that, you can invoke it like this: You might be interested in [this thread from the mailing list][5]. +### Building bare metal binaries + +`make run` builds and runs a binary designed to work on a POSIX platform, but +if you want to build binaries designed to run on bare metal, it's another +matter. + +For now, only the x86 PC platform is supported (work in progress in fact) and +can be built with `make pc.bin`. If you have QEMU installed, you can run it +right away with `make pcrun`. + [1]: http://collapseos.org [2]: http://collapseos.org/why.html [3]: https://sr.ht/~vdupras/duskos diff --git a/buildpc.fs b/buildpc.fs @@ -1,6 +1,6 @@ : spit ( a u -- ) >r begin c@+ stderr next ; -f<< /asm/i386.fs +1 to fecho f<< /xcomp/pc/mbr.fs -ORG $200 spit +org $200 spit f<< /xcomp/i386.fs -ORG here ORG - spit bye +org here org - spit bye diff --git a/fs/asm/i386.fs b/fs/asm/i386.fs @@ -190,7 +190,7 @@ $04e9 op jmp, $02e8 op call, : callfar, ( seg16 absaddr ) $9a c, dw, w, ; : forward! ( jmpaddr -- ) - c@+ $0f = if 1+ then pc over - ( a rel ) + c@+ $0f = if 1+ then here over - ( a rel ) is16bit? if 2 - swap w! else 4 - swap ! then ; \ Single operand diff --git a/fs/asm/label.fs b/fs/asm/label.fs @@ -8,4 +8,6 @@ : abs>rel ( a -- rel32 ) pc - ; -: forward here 0 ; +: forward here $10000 ; +: forward16 here $100 ; +: forward8 here 0 ; diff --git a/fs/doc/asm.txt b/fs/doc/asm.txt @@ -40,7 +40,7 @@ If the jump you want to use takes a relative address, you can use "abs>rel": mylabel abs>rel jmp, Forward jumps are something else. We don't know in advance what's the target pc, -so what we need to do is to emit the jump with a dummy value (0) and save the +so what we need to do is to emit the jump with a dummy value and save the address where the jump was written in a label. Then, when we reach that forward label location, we go back to the jump address saved and fiddle with its offset. @@ -61,3 +61,12 @@ and you would be quite right to ask these questions, because it's a tricky one. The answer is that the "forward!" word is implemented in an arch-specific manner and that it itself reads the target address and decode its own opcodes to answer those questions. + +Another question: how does "forward" know in advance the magnitude (4b? 2b? 1b?) +of the jump? In most assemblers, jump words auto-detect their width based on the +value they are passed. + +Answer: It doesn't. "forward" sends to jmp a value that intentionally doesn't +fit in 2b so that, by default, forward jumps don't end have space problems (at +the expense of binary space). If you want to create tighter forward jumps, use +"forward16" or "forward8" instead. diff --git a/fs/xcomp/i386.fs b/fs/xcomp/i386.fs @@ -2,9 +2,17 @@ \ has finished loading this binary as well as the Forth boot code following it \ in memory. We're in protected mode and all segments have been initialized. \ ESP and EBP are uninitialized. +?f<< /xcomp/tools.fs -$8000 const BINSTART \ This code lives at $8000. -create ORG -ax $07690748 i) mov, -$b8000 m) ax mov, -0 jmp, \ infinite loop +0 value L1 +$8000 to binstart \ This code lives at $8000. +here to org +forward8 jmp, to L1 + +xcode bye 0 jmp, + +xcode mainloop + L1 forward! + ax $07690748 i) mov, + $b8000 m) ax mov, + xwordlbl bye abs>rel call, diff --git a/fs/xcomp/pc/mbr.fs b/fs/xcomp/pc/mbr.fs @@ -1,19 +1,20 @@ \ x86 bootloader +?f<< /asm/i386.fs \ Bootsector is loaded at address $7c00 -$7c00 const BINSTART -BINSTART $1e0 + const GDTADDR +$7c00 to binstart +binstart $1e0 + const GDTADDR 0 value L1 1 to realmode -create ORG here $400 0 fill -forward jmp, to L1 \ bypass BPB +here to org here $400 0 fill +forward8 jmp, to L1 \ bypass BPB $23 allot L1 forward! cli, cld, GDTADDR m) lgdt, ax $0003 i) mov, $10 int, \ video mode 80x25 \ read sector 2 from boot floppy in memory at address $8000 ax $0201 i) mov, bx $8000 i) mov, cx $0002 i) mov, dx $0000 i) mov, $13 int, ax cr0 mov, ax 1 i) or, cr0 ax mov, -$08 0 jmpfar, here ORG - BINSTART + here 4 - w! 0 to realmode +$08 0 jmpfar, here org - binstart + here 4 - w! 0 to realmode \ initialize all segments ax 16 i) mov, ds ax mov, @@ -24,11 +25,11 @@ fs ax mov, \ Jump to payload $08 $8000 jmpfar, \ Inspired by GNU grub at grub-core/kern/i386/realmode.S -ORG $1e0 + to here \ GDT +org $1e0 + to here \ GDT \ First entry (the null entry) is a reference to itself $17 w, GDTADDR , 0 w, \ Code segment. base=0, limit=ffffff*4kb, present, execute/read, DPL=0 $ffff w, 0 w, 0 c, $9a c, $cf c, 0 c, \ Data segment. base=0, limit=ffffff*4kb, present, read/write, DPL=0 $ffff w, 0 w, 0 c, $92 c, $cf c, 0 c, -ORG $1fe + to here $55 c, $aa c, +org $1fe + to here $55 c, $aa c, diff --git a/fs/xcomp/tools.fs b/fs/xcomp/tools.fs @@ -0,0 +1,23 @@ +\ Tools for cross-compiling binaries +\ In Dusk, we don't support cross-compiling Forth. It's too hairy. Here, we're +\ only talking about cross-compiling assembler code, with, optionally, a Forth +\ dict in it. + +?f<< /lib/xdict.fs +?f<< /asm/label.fs \ org and binstart are there + +newxdict xbindict + +: xoffset binstart org - ; +: xcode word xbindict xentry ; + +\ Usage: xwordlbl foo call, "foo" being a word name in xbindict +: xwordlbl ( "name" -- pc ) xbindict x' xoffset + ; + +\ Traverse xdict and change all its prev field values so that they are related +\ to current org+binstart. Once this is done, the xdict can't be traversed +\ anymore and becomes opaque binary contents. +: orgifydict ( xdict -- ) + begin ( a ) + ?dup while ( a ) @ dup xoffset + over ! ( prev ) repeat ; +