From e6b42204ef1b44464ffb71340de6d445b8240c27 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Sun, 21 Mar 2021 23:10:55 -0700 Subject: [PATCH] shell: read initial expression from secondary disk See shell/README.md for (extremely klunky) instructions. --- 400.mu | 3 +++ boot.subx | 30 +++++++++++++++++++++--------- mu-init.subx | 1 - shell/README.md | 17 ++++++++++++++++- shell/main.mu | 20 ++++++++++++++++++++ vocabulary.md | 2 ++ 6 files changed, 62 insertions(+), 11 deletions(-) diff --git a/400.mu b/400.mu index c60f17ca..391ca57d 100644 --- a/400.mu +++ b/400.mu @@ -8,6 +8,9 @@ sig draw-cursor-on-real-screen g: grapheme # keyboard sig read-key kbd: (addr keyboard) -> _/eax: byte +# disk +sig load-sector-string-from-primary-bus-secondary-drive LBAlo: byte, LBAmid: byte, LBAhi: byte, out: (addr stream byte) + # tests sig count-test-failure sig num-test-failures -> _/eax: int diff --git a/boot.subx b/boot.subx index 0573d19e..5dc8e5bc 100644 --- a/boot.subx +++ b/boot.subx @@ -916,20 +916,23 @@ Font: # offset 1800 (address 0x9400) == code 0x9400 -# Use 28-bit PIO mode to transfer one sector from the primary drive on the -# primary bus. +# Use 28-bit PIO mode to transfer a string spanning at most one sector (512 +# bytes) of data. # Inspired by https://colorforth.github.io/ide.html # # Resources: # https://wiki.osdev.org/ATA_PIO_Mode # https://forum.osdev.org/viewtopic.php?f=1&p=167798 # read-sector, according to https://www.scs.stanford.edu/11wi-cs140/pintos/specs/ata-3-std.pdf -read-a-sector: +# +# Currently assumes top 4 bits of the 28-bit LBA coordinate are 0. +load-sector-string-from-primary-bus-secondary-drive: # LBAlo: byte, LBAmid: byte, LBAhi: byte, out: (addr stream byte) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp # . save registers 50/push-eax + 51/push-ecx 52/push-edx # check for floating bus { @@ -944,26 +947,35 @@ read-a-sector: (ata-drive-select 0xf0) # primary bus, secondary drive; 4 LSBs contain 4 upper bits of LBA (here 0) (clear-ata-error) (ata-sector-count 1) - (ata-lba 0 0 0) # lower 24 bits of LBA + (ata-lba *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # lower 24 bits of LBA (ata-command 0x20) # read sectors with retries # poll for results (poll-ata-primary-bus-primary-drive-regular-status-word) # print out results ba/copy-to-edx 0x1f0/imm32 - b9/copy-to-ecx 0x10/imm32 + b9/copy-to-ecx 0x200/imm32 # 512 bytes per sector { 81 7/subop/compare %ecx 0/imm32 74/jump-if-= break/disp8 ed/read-port-dx-into-eax - (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %eax) - (move-cursor-to-left-margin-of-next-line 0) # 0=screen + # write 4 bytes to stream one at a time + (append-byte *(ebp+0x14) %eax) + 49/decrement-ecx + c1/shift 5/subop/right-padding-zeroes %eax 8/imm8 + (append-byte *(ebp+0x14) %eax) + 49/decrement-ecx + c1/shift 5/subop/right-padding-zeroes %eax 8/imm8 + (append-byte *(ebp+0x14) %eax) + 49/decrement-ecx + c1/shift 5/subop/right-padding-zeroes %eax 8/imm8 + (append-byte *(ebp+0x14) %eax) 49/decrement-ecx eb/jump loop/disp8 } - (abort "success") -$read-256-sectors:end: +$load-sector-string-from-primary-bus-secondary-drive:end: # . restore registers 5a/pop-to-edx + 59/pop-to-ecx 58/pop-to-eax # . epilogue 89/<- %esp 5/r32/ebp diff --git a/mu-init.subx b/mu-init.subx index 7857a8a1..bf9e5b0d 100644 --- a/mu-init.subx +++ b/mu-init.subx @@ -10,7 +10,6 @@ Entry: # initialize stack bd/copy-to-ebp 0/imm32 - (read-a-sector) # always first run tests (run-tests) (num-test-failures) # => eax diff --git a/shell/README.md b/shell/README.md index 7a6600c2..463f8e16 100644 --- a/shell/README.md +++ b/shell/README.md @@ -1,9 +1,24 @@ ### A prototype shell for the Mu computer -Currently runs a tiny subset of Lisp. To build and run it from the top-level: +Currently runs a tiny subset of Lisp. Steps to run it from the top-level: +1. Build it: ```sh $ ./translate shell/*.mu # generates disk.img +``` + +2. Create a data disk: +```sh +$ dd if=/dev/zero of=data.img count=20160 +``` + +3. Optionally load an s-expression into the disk: +```sh +$ echo '(+ 1 1)' |dd of=data.img conv=notrunc +``` + +4. Run it: +```sh $ qemu-system-i386 disk.img ``` diff --git a/shell/main.mu b/shell/main.mu index eb437b67..38683293 100644 --- a/shell/main.mu +++ b/shell/main.mu @@ -5,6 +5,7 @@ fn main { var sandbox-storage: sandbox var sandbox/esi: (addr sandbox) <- address sandbox-storage initialize-sandbox sandbox + load-sandbox-from-secondary-disk sandbox var width/eax: int <- copy 0 var height/ecx: int <- copy 0 width, height <- screen-size 0/screen @@ -20,3 +21,22 @@ fn main { loop } } + +# Read a null-terminated sequence of keys from secondary disk and load them +# into sandbox. +fn load-sandbox-from-secondary-disk _self: (addr sandbox) { + var self/esi: (addr sandbox) <- copy _self + var s-storage: (stream byte 0x200) + var s/ebx: (addr stream byte) <- address s-storage + load-sector-string-from-primary-bus-secondary-drive 0/lbalo, 0/lbamid, 0/lbahi, s + { + var done?/eax: boolean <- stream-empty? s + compare done?, 0/false + break-if-!= + var key/eax: byte <- read-byte s + compare key, 0/null + break-if-= + edit-sandbox self, key + loop + } +} diff --git a/vocabulary.md b/vocabulary.md index 1ecbdf8d..badf6b02 100644 --- a/vocabulary.md +++ b/vocabulary.md @@ -112,6 +112,8 @@ The most useful functions from 400.mu and later .mu files. Look for definitions - `append-byte-hex`: writes textual representation of lowest byte in hex to a stream of bytes. Does not write a '0x' prefix. - `read-byte`: reads a single byte from a stream of bytes. +- `read-grapheme`: reads a single unicode grapheme (up to 4 bytes containing a + single code-point encoded in utf-8) from a stream of bytes. #### reading/writing hex representations of integers