diff --git a/kernel/src/holeybytes/kernel_services/mem_serve.rs b/kernel/src/holeybytes/kernel_services/mem_serve.rs
index 6e39e3a..ccdedf6 100644
--- a/kernel/src/holeybytes/kernel_services/mem_serve.rs
+++ b/kernel/src/holeybytes/kernel_services/mem_serve.rs
@@ -1,6 +1,6 @@
 use {
     crate::holeybytes::{kernel_services::block_read, Vm},
-    alloc::alloc::{alloc, dealloc},
+    alloc::alloc::{alloc, alloc_zeroed, dealloc, realloc},
     core::alloc::Layout,
     log::{debug, info},
 };
@@ -49,8 +49,12 @@ pub fn memory_msg_handler(
     match msg_type {
         0 => unsafe {
             let page_count = u64::from_le_bytes(msg_vec[1..9].try_into().unwrap()) as usize;
-
-            let ptr = alloc(Layout::from_size_align_unchecked(page_count * 4096, 1));
+            let zeroed = msg_vec[9];
+            let ptr = if zeroed > 0 {
+                alloc_zeroed(Layout::from_size_align_unchecked(page_count * 4096, 8))
+            } else {
+                alloc(Layout::from_size_align_unchecked(page_count * 4096, 8))
+            };
 
             log::debug!("Allocating {} pages @ {:?}", page_count, ptr);
 
@@ -61,11 +65,12 @@ pub fn memory_msg_handler(
             let page_count = u64::from_le_bytes(msg_vec[1..9].try_into().unwrap()) as usize;
 
             let mptr = u64::from_le_bytes(msg_vec[9..17].try_into().unwrap()) as *mut u8;
+            debug_assert!(mptr.addr() & 0xFFFF000000000000 != 0);
             log::debug!("Deallocating {} pages @ {:?}", page_count, mptr);
 
             dealloc(
                 mptr,
-                Layout::from_size_align_unchecked(page_count * 4096, 1),
+                Layout::from_size_align_unchecked(page_count * 4096, 8),
             )
         },
         2 => {
@@ -108,6 +113,35 @@ pub fn memory_msg_handler(
             debug_assert!(dest.addr() & 0xFFFF000000000000 != 0);
             memset(dest, src, count, size);
         },
+        6 => unsafe {
+            let count = u64::from_le_bytes(msg_vec[1..9].try_into().unwrap_unchecked()) as usize;
+            let src = u64::from_le_bytes(msg_vec[9..17].try_into().unwrap_unchecked()) as *const u8;
+            let dest = u64::from_le_bytes(msg_vec[17..25].try_into().unwrap_unchecked()) as *mut u8;
+            debug_assert!(src.addr() & 0xFFFF000000000000 != 0);
+            debug_assert!(dest.addr() & 0xFFFF000000000000 != 0);
+            src.copy_to(dest, count);
+        },
+        7 => unsafe {
+            let page_count = u64::from_le_bytes(msg_vec[1..9].try_into().unwrap()) as usize;
+            let page_count_new = u64::from_le_bytes(msg_vec[9..17].try_into().unwrap()) as usize;
+            let ptr = u64::from_le_bytes(msg_vec[17..25].try_into().unwrap()) as *mut u8;
+            debug_assert!(ptr.addr() & 0xFFFF000000000000 != 0);
+            let ptr_new = realloc(
+                ptr,
+                Layout::from_size_align_unchecked(page_count * 4096, 8),
+                page_count_new * 4096,
+            );
+
+            log::debug!(
+                "Re-allocating {} (now {}) pages from {:?} to {:?}",
+                page_count,
+                page_count_new,
+                ptr,
+                ptr_new
+            );
+
+            vm.registers[1] = hbvm::value::Value(ptr_new as u64);
+        },
         _ => {
             log::debug!("Unknown memory service message type: {}", msg_type);
         }
diff --git a/sysdata/libraries/stn/src/memory.hb b/sysdata/libraries/stn/src/memory.hb
index c6b818e..abf8554 100644
--- a/sysdata/libraries/stn/src/memory.hb
+++ b/sysdata/libraries/stn/src/memory.hb
@@ -1,6 +1,4 @@
 $PAGE_SIZE := 4096
-$MAX_ALLOC := 0xFF
-$MAX_FREE := 0xFF
 
 $uninit := fn($Expr: type): Expr {
 	return idk
@@ -19,18 +17,22 @@ $calc_pages := fn($Expr: type, num: uint): uint {
 }
 
 // ! will be replaced, don't get attached
-alloc := fn($Expr: type, num: uint): ^Expr {
-	return @bitcast(request_page(@intcast(calc_pages(Expr, num))))
+$alloc := fn($Expr: type, num: uint): ^Expr {
+	return @bitcast(request_page(calc_pages(Expr, num * @sizeof(Expr)), false))
+}
+
+$alloc_zeroed := fn($Expr: type, num: uint): ^Expr {
+	return @bitcast(request_page(calc_pages(Expr, num * @sizeof(Expr)), true))
 }
 
 // ! stub
 $free := fn($Expr: type, ptr: ^Expr, num: uint): void {
-	release_page(@bitcast(ptr), @intcast(calc_pages(Expr, num)))
+	release_page(@bitcast(ptr), calc_pages(Expr, num * @sizeof(Expr)))
 }
 
-RqPageMsg := packed struct {a: u8, count: uint}
-$request_page := fn(count: uint): ^u8 {
-	return @eca(3, 2, &RqPageMsg.(0, count), @sizeof(RqPageMsg))
+RqPageMsg := packed struct {a: u8, count: uint, zeroed: bool}
+$request_page := fn(count: uint, zeroed: bool): ^u8 {
+	return @eca(3, 2, &RqPageMsg.(0, count, zeroed), @sizeof(RqPageMsg))
 }
 
 RlPageMsg := packed struct {a: u8, count: uint, ptr: ^u8}
@@ -76,4 +78,8 @@ $copy := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): void {
 SetMsg := packed struct {a: u8, count: uint, size: uint, src: ^u8, dest: ^u8}
 $set := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): void {
 	return @eca(3, 2, &SetMsg.(5, count, @sizeof(Expr), @bitcast(src), @bitcast(dest)), @sizeof(SetMsg))
+}
+
+$move := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): void {
+	return @eca(3, 2, &CopyMsg.(7, count * @sizeof(Expr), @bitcast(src), @bitcast(dest)), @sizeof(CopyMsg))
 }
\ No newline at end of file
diff --git a/sysdata/programs/test/src/tests/stn/assets/hello_world_and_spin.hb b/sysdata/programs/test/src/tests/stn/assets/hello_world_and_spin.hb
deleted file mode 100644
index e8d4c92..0000000
--- a/sysdata/programs/test/src/tests/stn/assets/hello_world_and_spin.hb
+++ /dev/null
@@ -1,7 +0,0 @@
-.{log, sleep} := @use("stn")
-
-main := fn(): void {
-	log.info("Hello, World!")
-	// fake interrupt, sleep forever
-	sleep.sleep_until_interrupt(100)
-}
\ No newline at end of file
diff --git a/sysdata/programs/test/src/tests/stn/assets/hello_world_and_spin.hbf b/sysdata/programs/test/src/tests/stn/assets/hello_world_and_spin.hbf
deleted file mode 100644
index 48b1402..0000000
Binary files a/sysdata/programs/test/src/tests/stn/assets/hello_world_and_spin.hbf and /dev/null differ
diff --git a/sysdata/programs/test/src/tests/stn/assets/lily.axe b/sysdata/programs/test/src/tests/stn/assets/lily.axe
new file mode 100644
index 0000000..ff23ae1
Binary files /dev/null and b/sysdata/programs/test/src/tests/stn/assets/lily.axe differ
diff --git a/sysdata/programs/test/src/tests/stn/assets/lily.hbf b/sysdata/programs/test/src/tests/stn/assets/lily.hbf
deleted file mode 100644
index f85d5e6..0000000
Binary files a/sysdata/programs/test/src/tests/stn/assets/lily.hbf and /dev/null differ
diff --git a/sysdata/programs/test/src/tests/stn/process.hb b/sysdata/programs/test/src/tests/stn/process.hb
index cf3d22c..96b879b 100644
--- a/sysdata/programs/test/src/tests/stn/process.hb
+++ b/sysdata/programs/test/src/tests/stn/process.hb
@@ -1,7 +1,7 @@
 .{process, log} := @use("stn")
 
 // src: https://git.ablecorp.us/koniifer/lily
-exe := @embed("./assets/lily.hbf")
+exe := @embed("./assets/lily.axe")
 
 test := fn(): uint {
 	process.spawn(@bitcast(&exe), @sizeof(@TypeOf(exe)))