about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rwxr-xr-xapps/survey_baremetalbin51197 -> 51197 bytes
-rw-r--r--apps/survey_baremetal.subx34
-rw-r--r--baremetal/101screen.subx2
-rw-r--r--baremetal/102keyboard.subx12
-rw-r--r--baremetal/103grapheme.subx6
-rw-r--r--baremetal/README.md2
-rw-r--r--baremetal/boot.hex360
-rw-r--r--baremetal/ex2.hex2
-rw-r--r--baremetal/ex2.subx2
-rw-r--r--baremetal/mu-init.subx1
10 files changed, 273 insertions, 148 deletions
diff --git a/apps/survey_baremetal b/apps/survey_baremetal
index 6c254711..3bddb653 100755
--- a/apps/survey_baremetal
+++ b/apps/survey_baremetal
Binary files differdiff --git a/apps/survey_baremetal.subx b/apps/survey_baremetal.subx
index 7b0815ba..c42cd900 100644
--- a/apps/survey_baremetal.subx
+++ b/apps/survey_baremetal.subx
@@ -7,7 +7,7 @@
 #
 # The expected input is a stream of bytes and some interspersed labels.
 # Comments and '==' segment headers are allowed, but ignored. The emitted code
-# will all lie in a single header, and start at address 0x9000.
+# will all lie in a single header, and start at address 0x9400.
 #   $ cat x
 #   == code
 #   l1:
@@ -197,7 +197,7 @@ test-subx-survey-computes-addresses:
     #     01
     #
     # trace contains (in any order):
-    #   label x is at address 0x9005
+    #   label x is at address 0x9405
     #
     # . prologue
     55/push-ebp
@@ -315,10 +315,10 @@ test-subx-survey-computes-addresses:
 #?     # . . discard args
 #?     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
 #?     # }}}
-    # . check-trace-contains("label 'x' is at address 0x00009005.", msg)
+    # . check-trace-contains("label 'x' is at address 0x00009405.", msg)
     # . . push args
     68/push  "F - test-subx-survey-computes-addresses/0"/imm32
-    68/push  "label 'x' is at address 0x00009005."/imm32
+    68/push  "label 'x' is at address 0x00009405."/imm32
     # . . call
     e8/call  check-trace-contains/disp32
     # . . discard args
@@ -330,7 +330,7 @@ test-subx-survey-computes-addresses:
 
 compute-offsets:  # in: (addr stream byte), labels: (addr stream {(handle array byte), address})
     # pseudocode:
-    #   var current-address = 0x9000
+    #   var current-address = 0x9400
     #   var line: (stream byte 512)
     #   while true                                  # line loop
     #     clear-stream(line)
@@ -362,8 +362,8 @@ compute-offsets:  # in: (addr stream byte), labels: (addr stream {(handle array
     53/push-ebx
     56/push-esi
     57/push-edi
-    # var current-address/esi: int = 0x9000
-    be/copy-to-esi  0x9000/imm32
+    # var current-address/esi: int = 0x9400
+    be/copy-to-esi  0x9400/imm32
     # var line/ecx: (stream byte 512)
     81          5/subop/subtract    3/mod/direct    4/rm32/esp    .           .             .           .           .               0x200/imm32       # subtract from esp
     68/push  0x200/imm32/size
@@ -595,7 +595,7 @@ test-compute-offsets:
     #     34
     #
     # trace contains (in any order):
-    #   label 'x' is at address 0x9006.
+    #   label 'x' is at address 0x9406.
     #
     # . prologue
     55/push-ebp
@@ -697,10 +697,10 @@ test-compute-offsets:
 #?     # . . discard args
 #?     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
 #?     # }}}
-    # . check-trace-contains("label 'x' is at address 0x00009006.", msg)
+    # . check-trace-contains("label 'x' is at address 0x00009406.", msg)
     # . . push args
     68/push  "F - test-compute-offsets"/imm32
-    68/push  "label 'x' is at address 0x00009006."/imm32
+    68/push  "label 'x' is at address 0x00009406."/imm32
     # . . call
     e8/call  check-trace-contains/disp32
     # . . discard args
@@ -732,7 +732,7 @@ emit-output:datum:  # slice
 
 emit-output:  # in: (addr stream byte), out: (addr buffered-file), labels: (addr stream {(handle array byte), address})
     # pseudocode:
-    #   var address-of-next-instruction = 0x9000
+    #   var address-of-next-instruction = 0x9400
     #   var line: (stream byte 512)
     #   line-loop:
     #   while true
@@ -803,8 +803,8 @@ emit-output:  # in: (addr stream byte), out: (addr buffered-file), labels: (addr
     68/push  0/imm32/end
     68/push  0/imm32/start
     89/copy                         3/mod/direct    2/rm32/edx    .           .             .           4/r32/esp   .               .                 # copy esp to edx
-    # var address-of-next-instruction/ebx = 0x9000
-    bb/copy-to-ebx  0x9000/imm32
+    # var address-of-next-instruction/ebx = 0x9400
+    bb/copy-to-ebx  0x9400/imm32
 $emit-output:line-loop:
     # clear-stream(line)
     # . . push args
@@ -1491,12 +1491,12 @@ test-emit-output-code-label:
     #     ef gh
     #     e8 l1/disp32
     #   labels:
-    #     - 'l1': 0x9010
+    #     - 'l1': 0x9410
     #
     # output:
     #   ab cd
     #   ef gh
-    #   e8 07 00 00 00  # 0x9010 - 0x9009 = 7
+    #   e8 07 00 00 00  # 0x9410 - 0x9409 = 7
     #
     # . prologue
     55/push-ebp
@@ -1566,8 +1566,8 @@ test-emit-output-code-label:
     e8/call  write/disp32
     # . . discard args
     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-    # . stream-add2(labels, "l1", 0x9010)
-    68/push  0x9010/imm32/label-address
+    # . stream-add2(labels, "l1", 0x9410)
+    68/push  0x9410/imm32/label-address
     # . . push handle for "l1"
     53/push-ebx
     68/push  "l1"/imm32
diff --git a/baremetal/101screen.subx b/baremetal/101screen.subx
index c2229a59..cac9593e 100644
--- a/baremetal/101screen.subx
+++ b/baremetal/101screen.subx
@@ -28,7 +28,7 @@ pixel-on-real-screen:  # x: int, y: int, color: int
     c1/shift 4/subop/left %eax 0xa/imm8
     03/add-> *(ebp+8) 0/r32/eax
     # eax += location of frame buffer
-    03/add-> *0x7e28 0/r32/eax  # unsafe
+    03/add-> *0x7f28 0/r32/eax  # unsafe
     # *eax = color
     8b/-> *(ebp+0x10) 1/r32/ecx
     88/byte<- *eax 1/r32/CL
diff --git a/baremetal/102keyboard.subx b/baremetal/102keyboard.subx
index f2c22339..8faa71e3 100644
--- a/baremetal/102keyboard.subx
+++ b/baremetal/102keyboard.subx
@@ -20,19 +20,19 @@ read-key:  # kbd: (addr keyboard) -> result/eax: byte
     {
       75/jump-if-!= break/disp8
       # var read/ecx: byte = keyboard buffer's read index
-      8b/-> *0x7dcc 1/r32/CL  # keyboard-buffer-read
+      8b/-> *0x7ee4 1/r32/CL  # keyboard-buffer-read
       # var next-key/eax: byte = *(keyboard buffer + ecx)
-      8a/byte-> *(ecx+0x7dd0) 0/r32/AL  # keyboard-buffer-data
-      # if (next-key != 0) lock and remove from keyboard-buffer
+      8a/byte-> *(ecx+0x7ee8) 0/r32/AL  # keyboard-buffer-data
+      # if (next-key != 0) lock and remove from keyboard buffer
       81 7/subop/compare %eax 0/imm32
       {
         74/jump-if-= break/disp8
         # TODO: add some instructions in this block to SubX if we ever want to
         # use bootstrap on baremetal programs
         fa/disable-interrupts
-        c6 0/subop/copy-byte *(ecx+0x7dd0) 0/imm8
-        ff 0/subop/increment *0x7dcc  # keyboard-buffer-read
-        81 4/subop/and *0x7dcc 0xf/imm32  # keyboard-buffer-read
+        c6 0/subop/copy-byte *(ecx+0x7ee8) 0/imm8  # keyboard-buffer-data
+        ff 0/subop/increment *0x7ee4  # keyboard-buffer-read
+        81 4/subop/and *0x7ee4 0xf/imm32  # keyboard-buffer-read
         fb/enable-interrupts
       }
       # return
diff --git a/baremetal/103grapheme.subx b/baremetal/103grapheme.subx
index 16a44fbc..841abf6c 100644
--- a/baremetal/103grapheme.subx
+++ b/baremetal/103grapheme.subx
@@ -25,9 +25,9 @@ draw-grapheme-on-real-screen:  # g: grapheme, x: int, y: int, color: int, backgr
     # var letter-bitmap/esi = font[g]
     8b/-> *(ebp+8) 6/r32/esi
     c1 4/subop/shift-left %esi 4/imm8
-    8d/copy-address *(esi+0x8800) 6/r32/esi  # font-start
-    # if (letter-bitmap >= 0x9000) return  # characters beyond ASCII currently not supported
-    81 7/subop/compare %esi 0x9000/imm32
+    8d/copy-address *(esi+0x8c00) 6/r32/esi  # font-start
+    # if (letter-bitmap >= 0x9400) return  # characters beyond ASCII currently not supported
+    81 7/subop/compare %esi 0x9400/imm32
     7d/jump-if->= $draw-grapheme-on-real-screen:end/disp8
     # var ycurr/edx: int = y*16
     8b/-> *(ebp+0x10) 2/r32/edx
diff --git a/baremetal/README.md b/baremetal/README.md
index c4cf3efa..f9f3b493 100644
--- a/baremetal/README.md
+++ b/baremetal/README.md
@@ -30,7 +30,7 @@ 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.
 
-Programs start executing at address 0x9000. See baremetal/boot.hex for
+Programs start executing at address 0x9400. See baremetal/boot.hex for
 details.
 
 Mu programs always run all their automated tests first. `main` only runs if
diff --git a/baremetal/boot.hex b/baremetal/boot.hex
index b54aaa52..dd3e1f74 100644
--- a/baremetal/boot.hex
+++ b/baremetal/boot.hex
@@ -24,7 +24,7 @@
 # This file contains just lowercase hex bytes and comments. Zero
 # error-checking. Make liberal use of:
 #   - comments documenting expected offsets
-#   - size checks on the emitted file (currently: 5120 bytes)
+#   - size checks on the emitted file (currently: 6144 bytes)
 #   - xxd to eyeball that offsets contain expected bytes
 #
 # Programs using this initialization:
@@ -34,20 +34,24 @@
 #   - must start executing immediately after this file (see outline below)
 
 # Outline of this file with offsets and the addresses they map to at run-time:
-#   offset    0 (address 7c00): boot code, 16-bit mode
-#            80 (address 7c80) global descriptor table
-#            a0 (address 7ca0) <== gdt_descriptor
-#   offset   e0 (address 7ce0): boot code
-#   offset  100 (address 7d00): interrupt handler code
-#           1c8 (address 7dc8) <== keyboard buffer
-#           1f8 (address 7df8) <== idt_descriptor
+# -- 16-bit mode code
+#   offset    0 (address 7c00): boot code
+# -- 16-bit mode data
+#            e0 (address 7c80) global descriptor table
+#            f8 (address 7ca0) <== gdt_descriptor
+# -- 32-bit mode code
+#   offset  100 (address 7d00): boot code
 #           1fe (address 7dfe) boot sector marker (2 bytes)
-#   offset  200 (address 7e00): video mode data (256 bytes)
-#           228 (address 7e28) <== start of video RAM stored here
-#   offset  300 (address 7f00): interrupt descriptor table (256 bytes)
-#   offset  400 (address 8000): keyboard mappings (2KB)
-#   offset  c00 (address 8800): bitmap font (2KB)
-#   offset 1400 (address 9000): entrypoint for applications (don't forget to adjust survey_baremetal if this changes)
+#   offset  200 (address 7e00): interrupt handler code
+# -- 32-bit mode data
+#           2e0 (address 7ee0) <== keyboard buffer
+#           2f8 (address 7ef8) <== idt_descriptor
+#   offset  300 (address 7f00): video mode data (256 bytes)
+#           328 (address 7f28) <== start of video RAM stored here
+#   offset  400 (address 8000): interrupt descriptor table (1KB)
+#   offset  800 (address 8400): keyboard mappings (2KB)
+#   offset 1000 (address 8c00): bitmap font (2KB)
+#   offset 1800 (address 9400): entrypoint for applications (don't forget to adjust survey_baremetal if this changes)
 
 ## 16-bit entry point
 
@@ -90,7 +94,7 @@
   cd 13  # int 13h, BIOS disk service
   0f 82 8a 00  # jump-if-carry disk_error [label]
 # 26:
-  # load 63 sectors from disk into addresses [0xfa00, 0x17800)
+  # load second track from disk into addresses [0xfa00, 0x17800)
   b4 02  # ah <- 2  # read sectors from disk
   b5 00  # ch <- 0  # cylinder 0
   b6 01  # dh <- 1  # track 1
@@ -145,21 +149,48 @@
   b4 4f  # ah <- 4f (VBE)
   b0 01  # al <- 01 (get video mode)
   b9 07 01  # cx <- 0x0107 (mode we requested)
-  bf 00 7e  # di <- 0x7e00 (video mode info) [label]
+  bf 00 7f  # di <- 0x7f00 (video mode info) [label]
   cd 10
 
 # 6c:
   # switch to 32-bit mode
   0f 01 16  # lgdt 00/mod/indirect 010/subop 110/rm/use-disp16
-    a0 7c  # *gdt_descriptor [label]
+    f8 7c  # *gdt_descriptor [label]
   0f 20 c0  # eax <- cr0
   66 83 c8 01  # eax <- or 0x1
   0f 22 c0  # cr0 <- eax
-  ea e0 7c 08 00  # far jump to initialize_32bit_mode after setting cs to the record at offset 8 in the gdt (gdt_code) [label]
+  ea 00 7d 08 00  # far jump to initialize_32bit_mode after setting cs to the record at offset 8 in the gdt (gdt_code) [label]
+
+# padding
+# 80:
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+# cf:
+# disk_error:
+  # print 'D' to top-left of screen to indicate disk error
+  # *0xb8000 <- 0x0f44
+  # bx <- 0xb800
+  bb 00 b8
+  # ds <- bx
+  8e db  # 11b/mod 011b/reg/ds 011b/rm/bx
+  # al <- 'D'
+  b0 44
+  # ah <- 0x0f  # white on black
+  b4 0f
+  # bx <- 0
+  bb 00 00
+  # *ds:bx <- ax
+  89 07  # 00b/mod/indirect 000b/reg/ax 111b/rm/bx
+
+e9 fd ff  # loop forever
 
 ## GDT: 3 records of 8 bytes each
 
-# 80:
+# e0:
 # gdt_start:
 # gdt_null:  mandatory null descriptor
   00 00 00 00 00 00 00 00
@@ -180,46 +211,18 @@
   00  # base[24:32]
 # gdt_end:
 
-# padding
-# 98:
-                        00 00 00 00 00 00 00 00
-
-# a0:
+# f8:
 # gdt_descriptor:
   17 00  # final index of gdt = gdt_end - gdt_start - 1
-  80 7c 00 00  # start = gdt_start [label]
-
-# padding
-# a5:
-                  00 00 00 00 00 00 00 00 00 00
-
-# b0:
-# disk_error:
-  # print 'D' to top-left of screen to indicate disk error
-  # *0xb8000 <- 0x0f44
-  # bx <- 0xb800
-  bb 00 b8
-  # ds <- bx
-  8e db  # 11b/mod 011b/reg/ds 011b/rm/bx
-  # al <- 'D'
-  b0 44
-  # ah <- 0x0f  # white on black
-  b4 0f
-  # bx <- 0
-  bb 00 00
-  # *ds:bx <- ax
-  89 07  # 00b/mod/indirect 000b/reg/ax 111b/rm/bx
-
-e9 fd ff  # loop forever
+  e0 7c 00 00  # start = gdt_start [label]
 
 # padding
-# c1:
-   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+# fe:
+                                          00 00
 
 ## 32-bit code from this point (still some instructions not in SubX)
 
-# e0:
+# offset 100 (address 0x7d00):
 # initialize_32bit_mode:
   66 b8 10 00  # ax <- offset 16 from gdt_start
   8e d8  # ds <- ax
@@ -228,9 +231,10 @@ e9 fd ff  # loop forever
   8e e0  # fs <- ax
   8e e8  # gs <- ax
 
+# 10e:
   # load interrupt handlers
   0f 01 1d  # lidt 00/mod/indirect 011/subop 101/rm32/use-disp32
-    f8 7d 00 00  # *idt_descriptor [label]
+    f8 7e 00 00  # *idt_descriptor [label]
 
   # For now, not bothering reprogramming the IRQ to not conflict with software
   # exceptions.
@@ -241,27 +245,49 @@ e9 fd ff  # loop forever
   # Reference:
   #   https://wiki.osdev.org/Exceptions
 
+# 115:
   # enable keyboard IRQ (1)
   b0 fd  # al <- 0xfd  # disable mask for IRQ1
   e6 21  # port 0x21 <- al
 
+# 119:
   # initialization is done; enable interrupts
   fb
-  e9 01 13 00 00  # jump to 0x9000 [label]
+  e9 e1 16 00 00  # jump to 0x9400 [label]
 
 # padding
-# ff:
+# 11f:
                                              00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+# 1fe:
+# final 2 bytes of boot sector
+55 aa
+
+## sector 2 onwards loaded by load_disk, not automatically on boot
 
-# 100:
+# offset 200 (address 0x7e00):
 # null interrupt handler:
   cf  # iret
 
 # padding
-# 101:
+# 201:
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 
-# 110:
+# 210:
 # keyboard interrupt handler:
   # prologue
   fa  # disable interrupts
@@ -276,20 +302,20 @@ e9 fd ff  # loop forever
   24 01  # al <- and 0x1
   3c 00  # compare al, 0
   74 39  # jump to epilogue if = [label]
-# 120:
+# 220:
   # if keyboard buffer is full, return
   31 c9  # ecx <- xor ecx;  11/direct 001/r32/ecx 001/rm32/ecx
   # . var index/ecx: byte
   8a  # copy m8 at r32 to r8
     0d  # 00/mod/indirect 001/r8/cl 101/rm32/use-disp32
-    c8 7d 00 00  # disp32 [label]
+    e0 7e 00 00  # disp32 [label]
   # . al = *(keyboard buffer + index)
   8a  # copy m8 at r32 to r8
     81  # 10/mod/*+disp32 000/r8/al 001/rm32/ecx
-    d0 7d 00 00  # disp32 [label]
+    e8 7e 00 00  # disp32 [label]
   # . if (al != 0) return
   3c 00  # compare al, 0
-# 130:
+# 230:
   75 27  # jump to epilogue if != [label]
   # read keycode into al
   e4 60  # al <- port 0x60
@@ -299,37 +325,37 @@ e9 fd ff  # loop forever
   3c 00  # compare al, 0
   58  # pop to eax (without touching flags)
   75 1d  # jump to epilogue if != [label]
-# 13c:
+# 23c:
   # al <- *(keyboard normal map + eax)
   8a  # copy m8 at rm32 to r8
     80  # 10/mod/*+disp32 000/r8/al 000/rm32/eax
-    00 80 00 00  # disp32 [label]
+    00 84 00 00  # disp32 [label]
   # if there's no character mapping, return
   3c 00  # compare al, 0
   74 13  # jump to epilogue if = [label]
-# 146:
+# 246:
   # store al in keyboard buffer
   88  # copy r8 to m8 at r32
     81  # 10/mod/*+disp32 000/r8/al 001/rm32/ecx
-    d0 7d 00 00  # disp32 [label]
-# 14c:
+    e8 7e 00 00  # disp32 [label]
+# 24c:
   # increment index
   fe  # increment byte
     05  # 00/mod/indirect 000/subop/increment 101/rm32/use-disp32
-    c8 7d 00 00  # disp32 [label]
+    e0 7e 00 00  # disp32 [label]
   # clear top nibble of index (keyboard buffer is circular)
   80  # and byte
     25  # 00/mod/indirect 100/subop/and 101/rm32/use-disp32
-    c8 7d 00 00  # disp32 [label]
+    e0 7e 00 00  # disp32 [label]
     0f  # imm8
-# 159:
+# 259:
   # epilogue
   61  # pop all registers
   fb  # enable interrupts
   cf  # iret
 
 # padding
-# 15c:
+# 25c:
                                     00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
@@ -337,76 +363,69 @@ e9 fd ff  # loop forever
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 
-# 1c8:
+# 2e0:
 # var keyboard circular buffer
 # write index: nibble
 # still take up 4 bytes so SubX can handle it
   00 00 00 00
-# 1cc:
+# 2e4:
 # read index: nibble
 # still take up 4 bytes so SubX can handle it
   00 00 00 00
-# 1d0:
+# 2e8:
 # circular buffer: byte[16]
   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 
-# padding
-# 1e0:
-00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-00 00 00 00 00 00 00 00
-
-# 1f8:
+# 2f8:
 # idt_descriptor:
   ff 00  # idt_end - idt_start - 1
-  00 7f 00 00  # start = idt_start [label]
-
-# 1fe:
-# final 2 bytes of boot sector
-55 aa
+  00 80 00 00  # start = idt_start [label]
 
-## sector 2
-# loaded by load_disk, not automatically on boot
+# padding
+# 2fe:
+                                          00 00
 
-# offset 200 (address 0x7e00):
+# offset 300 (address 0x7f00):
 # video mode info:
   00 00  # attributes
   00  # winA
   00  # winB
-# 204
+# 304
   00 00  # granularity
   00 00  # winsize
-# 208
+# 308
   00 00  # segmentA
   00 00  # segmentB
-# 20c
+# 30c
   00 00 00 00  # realFctPtr (who knows)
-# 210
+# 310
   00 00  # pitch
   00 00  # Xres
-# 214
+# 314
   00 00  # Yres
   00 00  # Wchar Ychar
-# 218
+# 318
   00  # planes
   00  # bpp
   00  # banks
   00  # memory_model
-# 21c
+# 31c
   00  # bank_size
   00  # image_pages
   00  # reserved
-# 21f
+# 31f
   00 00  # red_mask red_position
   00 00  # green_mask green_position
   00 00  # blue_mask blue_position
   00 00  # rsv_mask rsv_position
   00  # directcolor_attributes
-# 228
+# 328
   00 00 00 00  # physbase <== linear frame buffer
 
-# 22c
+# 32c
 # reserved for video mode info
                                     00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
@@ -423,8 +442,9 @@ e9 fd ff  # loop forever
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 
-# offset 300 (address 0x7f00): interrupt descriptor table
-# 32 entries * 8 bytes each = 256 bytes (0x100)
+# offset 400 (address 0x8000):
+# interrupt descriptor table {{{
+# 128 entries * 8 bytes each = 1024 bytes (0x400)
 # idt_start:
 
 00 00 00 00 00 00 00 00
@@ -440,14 +460,14 @@ e9 fd ff  # loop forever
 # https://wiki.osdev.org/index.php?title=Interrupts&oldid=25102#Default_PC_Interrupt_Vector_Assignment
 
 # entry 8: clock
-  00 7d  # target[0:16] = null interrupt handler [label]
+  00 7e  # target[0:16] = null interrupt handler [label]
   08 00  # segment selector (gdt_code)
   00  # unused
   8e  # 1/p 00/dpl 0 1110/type/32-bit-interrupt-gate
   00 00  # target[16:32]
 
 # entry 9: keyboard
-  10 7d  # target[0:16] = keyboard interrupt handler [label]
+  10 7e  # target[0:16] = keyboard interrupt handler [label]
   08 00  # segment selector (gdt_code)
   00  # unused
   8e  # 1/p 00/dpl 0 1110/type/32-bit-interrupt-gate
@@ -475,11 +495,114 @@ e9 fd ff  # loop forever
 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00
+
+# 500:
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+
+# 600:
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+
+# 700:
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
 # idt_end:
+# }}}
 
 ## the rest of this file has data
 
-# offset 400 (address 0x8000):
+# offset 800 (address 0x8400):
 # translating keys to ASCII {{{
 # keyboard normal map:
 00
@@ -487,22 +610,22 @@ e9 fd ff  # loop forever
    1b
 #     |<--- digits -------------->| -  =  bs
       31 32 33 34 35 36 37 38 39 30 2d 3d 08
-# offset 40f
+# offset 80f
 #  tb q  w  e  r  t  y  u  i  o  p  [  ]
    09 71 77 65 72 74 79 75 69 6f 70 5b 5d
-# offset 41c
+# offset 81c
 #                                         enter
                                           0a 00
-# offset 41e
+# offset 81e
 #     a  s  d  f  g  h  j  k  l  ;  '  `     \
       61 73 64 66 67 68 6a 6b 6c 3b 27 60 00 5c
-# offset 42c
+# offset 82c
 #     z  x  c  v  b  n  m  ,  .  /     *
       7a 78 63 76 62 6e 6d 2c 2e 2f 00 2a
-# offset 438
+# offset 838
 #                          space
                         00 20
-# offset 43a
+# offset 83a
                               00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
@@ -517,7 +640,7 @@ e9 fd ff  # loop forever
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 
-# 500:
+# 900:
 # keyboard shift map:
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
@@ -536,7 +659,7 @@ e9 fd ff  # loop forever
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 
-# 600:
+# a00:
 # keyboard ctrl map:
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
@@ -556,7 +679,7 @@ e9 fd ff  # loop forever
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 
 # padding (there might be more keyboard tables)
-# 700:
+# b00:
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
@@ -573,8 +696,7 @@ e9 fd ff  # loop forever
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-
-# 800:
+# c00:
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
@@ -591,6 +713,7 @@ e9 fd ff  # loop forever
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+# d00:
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
@@ -607,7 +730,7 @@ e9 fd ff  # loop forever
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-# a00:
+# e00:
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
@@ -624,6 +747,7 @@ e9 fd ff  # loop forever
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+# f00:
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
@@ -642,7 +766,7 @@ e9 fd ff  # loop forever
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 # }}}
 
-# offset c00 (address 0x8800)
+# offset 1000 (address 0x8c00)
 # Bitmaps for some ASCII characters (soon Unicode) {{{
 # Part of GNU Unifont
 # 8px wide, 16px tall
@@ -880,6 +1004,6 @@ e9 fd ff  # loop forever
   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 # }}}
 
-# offset 1400 (address 0x9000)
+# offset 1800 (address 0x9400)
 
 # vim:ft=subx
diff --git a/baremetal/ex2.hex b/baremetal/ex2.hex
index f3c12260..439a0e03 100644
--- a/baremetal/ex2.hex
+++ b/baremetal/ex2.hex
@@ -18,7 +18,7 @@
 # ecx <- LFB
 8b  # copy *rm32 to r32
   0d  # 00/mod/indirect 001/r32/ecx 101/rm32/use-disp32
-  28 7e 00 00 # disp32 [label]
+  28 7f 00 00 # disp32 [label]
 
 # eax <- LFB + 0xbffff (1024*768 - 1)
 8d  # copy-address rm32 to r32
diff --git a/baremetal/ex2.subx b/baremetal/ex2.subx
index b1f42114..57806e34 100644
--- a/baremetal/ex2.subx
+++ b/baremetal/ex2.subx
@@ -14,7 +14,7 @@
 
 main:
   # ecx <- start of video memory
-  8b/-> *0x7e28 1/r32/ecx
+  8b/-> *0x7f28 1/r32/ecx
 
   # eax <- final pixel of video memory
   8d/copy-address *(ecx + 0x0bffff) 0/r32/eax  # 0xbffff = 1024*768 - 1
diff --git a/baremetal/mu-init.subx b/baremetal/mu-init.subx
index 26b83451..a748e74b 100644
--- a/baremetal/mu-init.subx
+++ b/baremetal/mu-init.subx
@@ -8,6 +8,7 @@
 
 # initialize stack
 bd/copy-to-ebp 0/imm32
+bc/copy-to-esp 0x00070000/imm32  # consult https://wiki.osdev.org/Memory_Map_(x86) when modifying this
 # always first run tests
 (run-tests)
 (num-test-failures)  # => eax