about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--baremetal/104test.subx32
-rw-r--r--baremetal/400.mu4
-rw-r--r--baremetal/500clear-screen.mu17
-rw-r--r--baremetal/502test.mu18
-rw-r--r--baremetal/README.md7
-rw-r--r--baremetal/mu-init.subx12
6 files changed, 87 insertions, 3 deletions
diff --git a/baremetal/104test.subx b/baremetal/104test.subx
new file mode 100644
index 00000000..5b14049e
--- /dev/null
+++ b/baremetal/104test.subx
@@ -0,0 +1,32 @@
+# Some helpers needed only because Mu doesn't support globals at the moment.
+
+== code
+
+count-test-failure:
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    #
+    ff 0/subop/increment *Num-test-failures
+$count-test-failure:end:
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
+num-test-failures:  # -> _/eax: int
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    #
+    8b/-> *Num-test-failures 0/r32/eax
+$num-test-failures:end:
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
+== data
+
+Num-test-failures:
+  0/imm32
diff --git a/baremetal/400.mu b/baremetal/400.mu
index 0f345e01..ff84a643 100644
--- a/baremetal/400.mu
+++ b/baremetal/400.mu
@@ -7,6 +7,10 @@ sig set-cursor-position screen: (addr screen), x: int, y: int
 # keyboard
 sig read-key kbd: (addr keyboard) -> _/eax: byte
 
+# tests
+sig count-test-failure
+sig num-test-failures -> _/eax: int
+
 # streams
 sig clear-stream f: (addr stream _)
 sig rewind-stream f: (addr stream _)
diff --git a/baremetal/500clear-screen.mu b/baremetal/500clear-screen.mu
new file mode 100644
index 00000000..0dbcdee2
--- /dev/null
+++ b/baremetal/500clear-screen.mu
@@ -0,0 +1,17 @@
+fn clear-screen screen: (addr screen) {
+  var y/eax: int <- copy 0
+  {
+    compare y, 0x300  # 768
+    break-if->=
+    var x/edx: int <- copy 0
+    {
+      compare x, 0x400  # 1024
+      break-if->=
+      pixel 0, x, y, 0  # black
+      x <- increment
+      loop
+    }
+    y <- increment
+    loop
+  }
+}
diff --git a/baremetal/502test.mu b/baremetal/502test.mu
new file mode 100644
index 00000000..94063a70
--- /dev/null
+++ b/baremetal/502test.mu
@@ -0,0 +1,18 @@
+# print msg to screen if a != b, otherwise print "."
+fn check-ints-equal _a: int, b: int, msg: (addr array byte) {
+  var a/eax: int <- copy _a
+  compare a, b
+  {
+    break-if-=
+    draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0, msg, 3  # 3=cyan
+    count-test-failure
+  }
+  {
+    break-if-!=
+    draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0, ".", 3  # 3=cyan
+  }
+}
+
+fn test-check-ints-equal {
+  check-ints-equal 0, 0, "abc"
+}
diff --git a/baremetal/README.md b/baremetal/README.md
index 96e7c900..dcc78e71 100644
--- a/baremetal/README.md
+++ b/baremetal/README.md
@@ -30,8 +30,11 @@ operating systems. There's also currently no code/data segment separation,
 just labels and bytes. I promise not to write self-modifying code. Security
 and sandboxing is still an open question.
 
-Most programs here assume `main` starts at address 0x9000 (7KB or 14 disk
-sectors past the BIOS entrypoint). See baremetal/boot.hex for details.
+Programs start executing at address 0x9000. See baremetal/boot.hex for
+details.
+
+Mu programs always run all their automated tests first. `main` only runs if
+there are no failing tests. See baremetal/mu-init.subx for details.
 
 So far the programs have only been tested in Qemu and Bochs emulators.
 
diff --git a/baremetal/mu-init.subx b/baremetal/mu-init.subx
index 232b3b49..77e62ede 100644
--- a/baremetal/mu-init.subx
+++ b/baremetal/mu-init.subx
@@ -9,7 +9,17 @@
 # initialize stack
 bd/copy-to-ebp 0/imm32
 # no heap yet
-(main)
+#
+# always first run tests
+(run-tests)
+(num-test-failures)  # => eax
+# call main if tests all passed
+{
+  3d/compare-eax-and 0/imm32
+  75/jump-if-!= break/disp8
+  (clear-screen)
+  (main)
+}
 
 # hang indefinitely
 {