From 20d6be52405130930fde9ca5bb5e95131ba4e659 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Thu, 14 Jan 2021 14:03:32 -0800 Subject: 7520 --- html/baremetal/101screen.subx.html | 90 ++++---- html/baremetal/102keyboard.subx.html | 83 +++---- html/baremetal/103grapheme.subx.html | 226 +++++++++--------- html/baremetal/104test.subx.html | 93 ++++++++ html/baremetal/108write.subx.html | 271 +++++++++++----------- html/baremetal/112read-byte.subx.html | 75 +++--- html/baremetal/115write-byte.subx.html | 75 +++--- html/baremetal/120allocate.subx.html | 105 ++++----- html/baremetal/302stack_allocate.subx.html | 2 +- html/baremetal/309stream.subx.html | 4 +- html/baremetal/313index-bounds-check.subx.html | 20 +- html/baremetal/400.mu.html | 32 ++- html/baremetal/403unicode.mu.html | 12 +- html/baremetal/500clear-screen.mu.html | 79 +++++++ html/baremetal/501draw-text.mu.html | 307 ++++++++++++------------- html/baremetal/502test.mu.html | 82 +++++++ html/baremetal/503manhattan-line.mu.html | 4 +- html/baremetal/ex1.subx.html | 10 +- html/baremetal/ex2.mu.html | 2 +- html/baremetal/ex2.subx.html | 44 ++-- html/baremetal/ex3.mu.html | 4 +- html/baremetal/ex4.mu.html | 2 +- html/baremetal/ex6.mu.html | 10 +- html/baremetal/ex7.mu.html | 2 +- html/baremetal/mu-init.subx.html | 22 +- 25 files changed, 970 insertions(+), 686 deletions(-) create mode 100644 html/baremetal/104test.subx.html create mode 100644 html/baremetal/500clear-screen.mu.html create mode 100644 html/baremetal/502test.mu.html (limited to 'html/baremetal') diff --git a/html/baremetal/101screen.subx.html b/html/baremetal/101screen.subx.html index 038e8f78..1f204a59 100644 --- a/html/baremetal/101screen.subx.html +++ b/html/baremetal/101screen.subx.html @@ -56,50 +56,52 @@ if ('onhashchange' in window) {
  1 # Primitives for screen control.
  2 
- 3 pixel:  # screen: (addr screen), x: int, y: int, color: int
- 4     # . prologue
- 5     55/push-ebp
- 6     89/<- %ebp 4/r32/esp
- 7     # . save registers
- 8     50/push-eax
- 9     51/push-ecx
-10     # ecx = screen
-11     8b/-> *(ebp+8) 1/r32/ecx
-12     81 7/subop/compare %ecx 0/imm32
-13     {
-14       75/jump-if-!= break/disp8
-15       # bounds checks
-16       8b/-> *(ebp+0xc) 0/r32/eax
-17       3d/compare-eax-and 0/imm32
-18       7c/jump-if-< $pixel:end/disp8
-19       3d/compare-eax-and 0x400/imm32/1024
-20       7d/jump-if->= $pixel:end/disp8
-21       8b/-> *(ebp+0x10) 0/r32/eax
-22       3d/compare-eax-and 0/imm32
-23       7c/jump-if-< $pixel:end/disp8
-24       3d/compare-eax-and 0x300/imm32/768
-25       7d/jump-if->= $pixel:end/disp8
-26       # eax = y*1024 + x
-27       8b/-> *(ebp+0x10) 0/r32/eax
-28       c1/shift 4/subop/left %eax 0xa/imm8
-29       03/add-> *(ebp+0xc) 0/r32/eax
-30       # eax += location of frame buffer
-31       03/add-> *0x7f28 0/r32/eax
-32       # *eax = color
-33       8b/-> *(ebp+0x14) 1/r32/ecx
-34       88/byte<- *eax 1/r32/CL
-35       # return
-36       eb $pixel:end/disp8
-37     }
-38     # TODO: fake screen
-39 $pixel:end:
-40     # . restore registers
-41     59/pop-to-ecx
-42     58/pop-to-eax
-43     # . epilogue
-44     89/<- %esp 5/r32/ebp
-45     5d/pop-to-ebp
-46     c3/return
+ 3 == code
+ 4 
+ 5 pixel:  # screen: (addr screen), x: int, y: int, color: int
+ 6     # . prologue
+ 7     55/push-ebp
+ 8     89/<- %ebp 4/r32/esp
+ 9     # . save registers
+10     50/push-eax
+11     51/push-ecx
+12     # ecx = screen
+13     8b/-> *(ebp+8) 1/r32/ecx
+14     81 7/subop/compare %ecx 0/imm32
+15     {
+16       75/jump-if-!= break/disp8
+17       # bounds checks
+18       8b/-> *(ebp+0xc) 0/r32/eax
+19       3d/compare-eax-and 0/imm32
+20       7c/jump-if-< $pixel:end/disp8
+21       3d/compare-eax-and 0x400/imm32/1024
+22       7d/jump-if->= $pixel:end/disp8
+23       8b/-> *(ebp+0x10) 0/r32/eax
+24       3d/compare-eax-and 0/imm32
+25       7c/jump-if-< $pixel:end/disp8
+26       3d/compare-eax-and 0x300/imm32/768
+27       7d/jump-if->= $pixel:end/disp8
+28       # eax = y*1024 + x
+29       8b/-> *(ebp+0x10) 0/r32/eax
+30       c1/shift 4/subop/left %eax 0xa/imm8
+31       03/add-> *(ebp+0xc) 0/r32/eax
+32       # eax += location of frame buffer
+33       03/add-> *0x7f28 0/r32/eax
+34       # *eax = color
+35       8b/-> *(ebp+0x14) 1/r32/ecx
+36       88/byte<- *eax 1/r32/CL
+37       # return
+38       eb $pixel:end/disp8
+39     }
+40     # TODO: fake screen
+41 $pixel:end:
+42     # . restore registers
+43     59/pop-to-ecx
+44     58/pop-to-eax
+45     # . epilogue
+46     89/<- %esp 5/r32/ebp
+47     5d/pop-to-ebp
+48     c3/return
 
diff --git a/html/baremetal/102keyboard.subx.html b/html/baremetal/102keyboard.subx.html index cc092133..660d74fb 100644 --- a/html/baremetal/102keyboard.subx.html +++ b/html/baremetal/102keyboard.subx.html @@ -56,46 +56,49 @@ if ('onhashchange' in window) {
  1 # check keyboard for a key
  2 # return 0 on no keypress or unrecognized key
- 3 read-key:  # kbd: (addr keyboard) -> result/eax: byte
- 4     # . prologue
- 5     55/push-ebp
- 6     89/<- %ebp 4/r32/esp
- 7     # . save registers
- 8     51/push-ecx
- 9     # result = 0
-10     b8/copy-to-eax 0/imm32
-11     # ecx = keyboard
-12     8b/-> *(ebp+8) 1/r32/ecx
-13     81 7/subop/compare %ecx 0/imm32
-14     {
-15       75/jump-if-!= break/disp8
-16       # var read/ecx: byte = keyboard buffer's read index
-17       8b/-> *0x7dcc 1/r32/CL  # keyboard-buffer-read
-18       # var next-key/eax: byte = *(keyboard buffer + ecx)
-19       8a/byte-> *(ecx+0x7dd0) 0/r32/AL  # keyboard-buffer-data
-20       # if (next-key != 0) lock and remove from keyboard-buffer
-21       81 7/subop/compare %eax 0/imm32
-22       {
-23         74/jump-if-= break/disp8
-24         # TODO: add some instructions in this block to SubX if we ever want to
-25         # use bootstrap on baremetal programs
-26         fa/disable-interrupts
-27         c6 0/subop/copy-byte *(ecx+0x7dd0) 0/imm8
-28         ff 0/subop/increment *0x7dcc  # keyboard-buffer-read
-29         81 4/subop/and *0x7dcc 0xf/imm32  # keyboard-buffer-read
-30         fb/enable-interrupts
-31       }
-32       # return
-33       eb $read-key:end/disp8
-34     }
-35     # TODO: fake keyboard
-36 $read-key:end:
-37     # . restore registers
-38     59/pop-to-ecx
-39     # . epilogue
-40     89/<- %esp 5/r32/ebp
-41     5d/pop-to-ebp
-42     c3/return
+ 3 
+ 4 == code
+ 5 
+ 6 read-key:  # kbd: (addr keyboard) -> result/eax: byte
+ 7     # . prologue
+ 8     55/push-ebp
+ 9     89/<- %ebp 4/r32/esp
+10     # . save registers
+11     51/push-ecx
+12     # result = 0
+13     b8/copy-to-eax 0/imm32
+14     # ecx = keyboard
+15     8b/-> *(ebp+8) 1/r32/ecx
+16     81 7/subop/compare %ecx 0/imm32
+17     {
+18       75/jump-if-!= break/disp8
+19       # var read/ecx: byte = keyboard buffer's read index
+20       8b/-> *0x7dcc 1/r32/CL  # keyboard-buffer-read
+21       # var next-key/eax: byte = *(keyboard buffer + ecx)
+22       8a/byte-> *(ecx+0x7dd0) 0/r32/AL  # keyboard-buffer-data
+23       # if (next-key != 0) lock and remove from keyboard-buffer
+24       81 7/subop/compare %eax 0/imm32
+25       {
+26         74/jump-if-= break/disp8
+27         # TODO: add some instructions in this block to SubX if we ever want to
+28         # use bootstrap on baremetal programs
+29         fa/disable-interrupts
+30         c6 0/subop/copy-byte *(ecx+0x7dd0) 0/imm8
+31         ff 0/subop/increment *0x7dcc  # keyboard-buffer-read
+32         81 4/subop/and *0x7dcc 0xf/imm32  # keyboard-buffer-read
+33         fb/enable-interrupts
+34       }
+35       # return
+36       eb $read-key:end/disp8
+37     }
+38     # TODO: fake keyboard
+39 $read-key:end:
+40     # . restore registers
+41     59/pop-to-ecx
+42     # . epilogue
+43     89/<- %esp 5/r32/ebp
+44     5d/pop-to-ebp
+45     c3/return
 
diff --git a/html/baremetal/103grapheme.subx.html b/html/baremetal/103grapheme.subx.html index 13dc6073..77e1d901 100644 --- a/html/baremetal/103grapheme.subx.html +++ b/html/baremetal/103grapheme.subx.html @@ -55,117 +55,121 @@ if ('onhashchange' in window) { https://github.com/akkartik/mu/blob/main/baremetal/103grapheme.subx
-  1 draw-grapheme:  # screen: (addr screen), g: grapheme, x: int, y: int, color: int
-  2     # . prologue
-  3     55/push-ebp
-  4     89/<- %ebp 4/r32/esp
-  5     # . save registers
-  6     50/push-eax
-  7     51/push-ecx
-  8     52/push-edx
-  9     53/push-ebx
- 10     56/push-esi
- 11     # TODO: support fake screen; we currently assume 'screen' is always 0 (real)
- 12     # var letter-bitmap/esi = font[g]
- 13     8b/-> *(ebp+0xc) 6/r32/esi
- 14     c1 4/subop/shift-left %esi 4/imm8
- 15     8d/copy-address *(esi+0x8800) 6/r32/esi  # font-start
- 16     # if (letter-bitmap >= 0x9000) return  # characters beyond ASCII currently not supported
- 17     81 7/subop/compare %esi 0x9000/imm32
- 18     7d/jump-if->= $draw-grapheme:end/disp8
- 19     # edx = y
- 20     8b/-> *(ebp+0x14) 2/r32/edx
- 21     # var ymax/ebx: int = y + 16
- 22     8b/-> *(ebp+0x14) 3/r32/ebx
- 23     81 0/subop/add %ebx 0x10/imm32
- 24     {
- 25       # if (y >= ymax) break
- 26       39/compare %edx 3/r32/ebx
- 27       7d/jump-if->= break/disp8
- 28       # eax = x + 7
- 29       8b/-> *(ebp+0x10) 0/r32/eax
- 30       81 0/subop/add %eax 7/imm32
- 31       # var xmin/ecx: int = x
- 32       8b/-> *(ebp+0x10) 1/r32/ecx
- 33       # var row-bitmap/ebx: int = *letter-bitmap
- 34       53/push-ebx
- 35       8b/-> *esi 3/r32/ebx
- 36       {
- 37         # if (x < xmin) break
- 38         39/compare %eax 1/r32/ecx
- 39         7c/jump-if-< break/disp8
- 40         # shift LSB from row-bitmap into carry flag (CF)
- 41         c1 5/subop/shift-right-logical %ebx 1/imm8
- 42         # if LSB, draw a pixel
- 43         {
- 44           73/jump-if-not-CF break/disp8
- 45           (pixel *(ebp+8) %eax %edx *(ebp+0x18))
- 46         }
- 47         # --x
- 48         48/decrement-eax
- 49         #
- 50         eb/jump loop/disp8
- 51       }
- 52       # reclaim row-bitmap
- 53       5b/pop-to-ebx
- 54       # ++y
- 55       42/increment-edx
- 56       # next bitmap row
- 57       46/increment-esi
- 58       #
- 59       eb/jump loop/disp8
- 60     }
- 61 $draw-grapheme:end:
- 62     # . restore registers
- 63     5e/pop-to-esi
- 64     5b/pop-to-ebx
- 65     5a/pop-to-edx
- 66     59/pop-to-ecx
- 67     58/pop-to-eax
- 68     # . epilogue
- 69     89/<- %esp 5/r32/ebp
- 70     5d/pop-to-ebp
- 71     c3/return
- 72 
- 73 cursor-position:  # screen: (addr screen) -> _/eax: int, _/ecx: int
- 74     # . prologue
- 75     55/push-ebp
- 76     89/<- %ebp 4/r32/esp
- 77     # TODO: support fake screen; we currently assume 'screen' is always 0 (real)
- 78     8b/-> *Default-next-x 0/r32/eax
- 79     8b/-> *Default-next-y 1/r32/ecx
- 80 $cursor-position:end:
- 81     # . epilogue
- 82     89/<- %esp 5/r32/ebp
- 83     5d/pop-to-ebp
- 84     c3/return
- 85 
- 86 set-cursor-position:  # screen: (addr screen), x: int, y: int
- 87     # . prologue
- 88     55/push-ebp
- 89     89/<- %ebp 4/r32/esp
- 90     # . save registers
- 91     50/push-eax
- 92     # TODO: support fake screen; we currently assume 'screen' is always 0 (real)
- 93     8b/-> *(ebp+0xc) 0/r32/eax
- 94     89/<- *Default-next-x 0/r32/eax
- 95     8b/-> *(ebp+0x10) 0/r32/eax
- 96     89/<- *Default-next-y 0/r32/eax
- 97 $set-cursor-position:end:
- 98     # . restore registers
- 99     58/pop-to-eax
-100     # . epilogue
-101     89/<- %esp 5/r32/ebp
-102     5d/pop-to-ebp
-103     c3/return
-104 
-105 == data
-106 
-107 Default-next-x:
-108   0/imm32
-109 
-110 Default-next-y:
-111   0/imm32
+  1 # Use the built-in font to draw a grapheme to screen.
+  2 
+  3 == code
+  4 
+  5 draw-grapheme:  # screen: (addr screen), g: grapheme, x: int, y: int, color: int
+  6     # . prologue
+  7     55/push-ebp
+  8     89/<- %ebp 4/r32/esp
+  9     # . save registers
+ 10     50/push-eax
+ 11     51/push-ecx
+ 12     52/push-edx
+ 13     53/push-ebx
+ 14     56/push-esi
+ 15     # TODO: support fake screen; we currently assume 'screen' is always 0 (real)
+ 16     # var letter-bitmap/esi = font[g]
+ 17     8b/-> *(ebp+0xc) 6/r32/esi
+ 18     c1 4/subop/shift-left %esi 4/imm8
+ 19     8d/copy-address *(esi+0x8800) 6/r32/esi  # font-start
+ 20     # if (letter-bitmap >= 0x9000) return  # characters beyond ASCII currently not supported
+ 21     81 7/subop/compare %esi 0x9000/imm32
+ 22     7d/jump-if->= $draw-grapheme:end/disp8
+ 23     # edx = y
+ 24     8b/-> *(ebp+0x14) 2/r32/edx
+ 25     # var ymax/ebx: int = y + 16
+ 26     8b/-> *(ebp+0x14) 3/r32/ebx
+ 27     81 0/subop/add %ebx 0x10/imm32
+ 28     {
+ 29       # if (y >= ymax) break
+ 30       39/compare %edx 3/r32/ebx
+ 31       7d/jump-if->= break/disp8
+ 32       # eax = x + 7
+ 33       8b/-> *(ebp+0x10) 0/r32/eax
+ 34       81 0/subop/add %eax 7/imm32
+ 35       # var xmin/ecx: int = x
+ 36       8b/-> *(ebp+0x10) 1/r32/ecx
+ 37       # var row-bitmap/ebx: int = *letter-bitmap
+ 38       53/push-ebx
+ 39       8b/-> *esi 3/r32/ebx
+ 40       {
+ 41         # if (x < xmin) break
+ 42         39/compare %eax 1/r32/ecx
+ 43         7c/jump-if-< break/disp8
+ 44         # shift LSB from row-bitmap into carry flag (CF)
+ 45         c1 5/subop/shift-right-logical %ebx 1/imm8
+ 46         # if LSB, draw a pixel
+ 47         {
+ 48           73/jump-if-not-CF break/disp8
+ 49           (pixel *(ebp+8) %eax %edx *(ebp+0x18))
+ 50         }
+ 51         # --x
+ 52         48/decrement-eax
+ 53         #
+ 54         eb/jump loop/disp8
+ 55       }
+ 56       # reclaim row-bitmap
+ 57       5b/pop-to-ebx
+ 58       # ++y
+ 59       42/increment-edx
+ 60       # next bitmap row
+ 61       46/increment-esi
+ 62       #
+ 63       eb/jump loop/disp8
+ 64     }
+ 65 $draw-grapheme:end:
+ 66     # . restore registers
+ 67     5e/pop-to-esi
+ 68     5b/pop-to-ebx
+ 69     5a/pop-to-edx
+ 70     59/pop-to-ecx
+ 71     58/pop-to-eax
+ 72     # . epilogue
+ 73     89/<- %esp 5/r32/ebp
+ 74     5d/pop-to-ebp
+ 75     c3/return
+ 76 
+ 77 cursor-position:  # screen: (addr screen) -> _/eax: int, _/ecx: int
+ 78     # . prologue
+ 79     55/push-ebp
+ 80     89/<- %ebp 4/r32/esp
+ 81     # TODO: support fake screen; we currently assume 'screen' is always 0 (real)
+ 82     8b/-> *Default-next-x 0/r32/eax
+ 83     8b/-> *Default-next-y 1/r32/ecx
+ 84 $cursor-position:end:
+ 85     # . epilogue
+ 86     89/<- %esp 5/r32/ebp
+ 87     5d/pop-to-ebp
+ 88     c3/return
+ 89 
+ 90 set-cursor-position:  # screen: (addr screen), x: int, y: int
+ 91     # . prologue
+ 92     55/push-ebp
+ 93     89/<- %ebp 4/r32/esp
+ 94     # . save registers
+ 95     50/push-eax
+ 96     # TODO: support fake screen; we currently assume 'screen' is always 0 (real)
+ 97     8b/-> *(ebp+0xc) 0/r32/eax
+ 98     89/<- *Default-next-x 0/r32/eax
+ 99     8b/-> *(ebp+0x10) 0/r32/eax
+100     89/<- *Default-next-y 0/r32/eax
+101 $set-cursor-position:end:
+102     # . restore registers
+103     58/pop-to-eax
+104     # . epilogue
+105     89/<- %esp 5/r32/ebp
+106     5d/pop-to-ebp
+107     c3/return
+108 
+109 == data
+110 
+111 Default-next-x:
+112   0/imm32
+113 
+114 Default-next-y:
+115   0/imm32
 
diff --git a/html/baremetal/104test.subx.html b/html/baremetal/104test.subx.html new file mode 100644 index 00000000..ef99acf6 --- /dev/null +++ b/html/baremetal/104test.subx.html @@ -0,0 +1,93 @@ + + + + +Mu - baremetal/104test.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/main/baremetal/104test.subx +
+ 1 # Some helpers needed only because Mu doesn't support globals at the moment.
+ 2 
+ 3 == code
+ 4 
+ 5 count-test-failure:
+ 6     # . prologue
+ 7     55/push-ebp
+ 8     89/<- %ebp 4/r32/esp
+ 9     #
+10     ff 0/subop/increment *Num-test-failures
+11 $count-test-failure:end:
+12     # . epilogue
+13     89/<- %esp 5/r32/ebp
+14     5d/pop-to-ebp
+15     c3/return
+16 
+17 num-test-failures:  # -> _/eax: int
+18     # . prologue
+19     55/push-ebp
+20     89/<- %ebp 4/r32/esp
+21     #
+22     8b/-> *Num-test-failures 0/r32/eax
+23 $num-test-failures:end:
+24     # . epilogue
+25     89/<- %esp 5/r32/ebp
+26     5d/pop-to-ebp
+27     c3/return
+28 
+29 == data
+30 
+31 Num-test-failures:
+32   0/imm32
+
+ + + diff --git a/html/baremetal/108write.subx.html b/html/baremetal/108write.subx.html index 608ddb82..5253c1fa 100644 --- a/html/baremetal/108write.subx.html +++ b/html/baremetal/108write.subx.html @@ -57,141 +57,142 @@ if ('onhashchange' in window) { https://github.com/akkartik/mu/blob/main/baremetal/108write.subx
-  1 #   instruction                     effective address                                                   register    displacement    immediate
-  2 # . op          subop               mod             rm32          base        index         scale       r32
-  3 # . 1-3 bytes   3 bits              2 bits          3 bits        3 bits      3 bits        2 bits      2 bits      0/1/2/4 bytes   0/1/2/4 bytes
-  4 
-  5 write:  # f: (addr stream byte), s: (addr array byte)
-  6     # . prologue
-  7     55/push-ebp
-  8     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
-  9     # if (s == 0) return
- 10     81          7/subop/compare     1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       0/imm32           # compare *(ebp+12)
- 11     74/jump-if-=  $write:end/disp8
- 12     # TODO: write to file
- 13     # otherwise, treat 'f' as a stream to append to
- 14     # . save registers
- 15     50/push-eax
- 16     51/push-ecx
- 17     52/push-edx
- 18     53/push-ebx
- 19     # ecx = f
- 20     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .                         1/r32/ecx   8/disp8         .                 # copy *(ebp+8) to ecx
- 21     # edx = f->write
- 22     8b/copy                         0/mod/indirect  1/rm32/ecx    .           .             .           2/r32/edx   .               .                 # copy *ecx to edx
- 23     # ebx = f->size
- 24     8b/copy                         1/mod/*+disp8   1/rm32/ecx    .           .             .           3/r32/ebx   8/disp8         .                 # copy *(ecx+8) to ebx
- 25     # eax = _append-3(&f->data[f->write], &f->data[f->size], s)
- 26     # . . push s
- 27     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
- 28     # . . push &f->data[f->size]
- 29     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    1/base/ecx  3/index/ebx   .           3/r32/ebx   0xc/disp8       .                 # copy ecx+ebx+12 to ebx
- 30     53/push-ebx
- 31     # . . push &f->data[f->write]
- 32     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    1/base/ecx  2/index/edx   .           3/r32/ebx   0xc/disp8       .                 # copy ecx+edx+12 to ebx
- 33     53/push-ebx
- 34     # . . call
- 35     e8/call  _append-3/disp32
- 36     # . . discard args
- 37     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
- 38     # f->write += eax
- 39     01/add                          0/mod/indirect  1/rm32/ecx    .           .             .           0/r32/eax   .               .                 # add eax to *ecx
- 40     # . restore registers
- 41     5b/pop-to-ebx
- 42     5a/pop-to-edx
- 43     59/pop-to-ecx
- 44     58/pop-to-eax
- 45 $write:end:
- 46     # . epilogue
- 47     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
- 48     5d/pop-to-ebp
- 49     c3/return
- 50 
- 51 # TODO: bring in tests once we have check-ints-equal
- 52 
- 53 # 3-argument variant of _append
- 54 _append-3:  # out: (addr byte), outend: (addr byte), s: (addr array byte) -> num_bytes_appended/eax
- 55     # . prologue
- 56     55/push-ebp
- 57     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
- 58     # . save registers
- 59     51/push-ecx
- 60     # eax = _append-4(out, outend, &s->data[0], &s->data[s->size])
- 61     # . . push &s->data[s->size]
- 62     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .                         0/r32/eax   0x10/disp8      .                 # copy *(ebp+16) to eax
- 63     8b/copy                         0/mod/indirect  0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # copy *eax to ecx
- 64     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    0/base/eax  1/index/ecx   .           1/r32/ecx   4/disp8         .                 # copy eax+ecx+4 to ecx
- 65     51/push-ecx
- 66     # . . push &s->data[0]
- 67     8d/copy-address                 1/mod/*+disp8   0/rm32/eax    .           .             .           1/r32/ecx   4/disp8         .                 # copy eax+4 to ecx
- 68     51/push-ecx
- 69     # . . push outend
- 70     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
- 71     # . . push out
- 72     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
- 73     # . . call
- 74     e8/call  _append-4/disp32
- 75     # . . discard args
- 76     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x10/imm32        # add to esp
- 77 $_append-3:end:
- 78     # . restore registers
- 79     59/pop-to-ecx
- 80     # . epilogue
- 81     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
- 82     5d/pop-to-ebp
- 83     c3/return
- 84 
- 85 # 4-argument variant of _append
- 86 _append-4:  # out: (addr byte), outend: (addr byte), in: (addr byte), inend: (addr byte) -> num_bytes_appended/eax: int
- 87     # . prologue
- 88     55/push-ebp
- 89     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
- 90     # . save registers
- 91     51/push-ecx
- 92     52/push-edx
- 93     53/push-ebx
- 94     56/push-esi
- 95     57/push-edi
- 96     # num_bytes_appended = 0
- 97     b8/copy-to-eax  0/imm32
- 98     # edi = out
- 99     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           7/r32/edi   8/disp8         .                 # copy *(ebp+8) to edi
-100     # edx = outend
-101     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           2/r32/edx   0xc/disp8       .                 # copy *(ebp+12) to edx
-102     # esi = in
-103     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   0x10/disp8      .                 # copy *(ebp+16) to esi
-104     # ecx = inend
-105     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           1/r32/ecx   0x14/disp8      .                 # copy *(ebp+20) to ecx
-106 $_append-4:loop:
-107     # if (in >= inend) break
-108     39/compare                      3/mod/direct    6/rm32/esi    .           .             .           1/r32/ecx   .               .                 # compare esi with ecx
-109     73/jump-if-addr>=  $_append-4:end/disp8
-110     # if (out >= outend) abort  # just to catch test failures fast
-111     39/compare                      3/mod/direct    7/rm32/edi    .           .             .           2/r32/edx   .               .                 # compare edi with edx
-112     73/jump-if-addr>=  $_append-4:end/disp8  # TODO: abort
-113     # *out = *in
-114     8a/copy-byte                    0/mod/indirect  6/rm32/esi    .           .             .           3/r32/BL    .               .                 # copy byte at *esi to BL
-115     88/copy-byte                    0/mod/indirect  7/rm32/edi    .           .             .           3/r32/BL    .               .                 # copy byte at BL to *edi
-116     # ++num_bytes_appended
-117     40/increment-eax
-118     # ++in
-119     46/increment-esi
-120     # ++out
-121     47/increment-edi
-122     eb/jump  $_append-4:loop/disp8
-123 $_append-4:end:
-124     # . restore registers
-125     5f/pop-to-edi
-126     5e/pop-to-esi
-127     5b/pop-to-ebx
-128     5a/pop-to-edx
-129     59/pop-to-ecx
-130     # . epilogue
-131     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
-132     5d/pop-to-ebp
-133     c3/return
-134 
-135 # . . vim:nowrap:textwidth=0
+  1 == code
+  2 #   instruction                     effective address                                                   register    displacement    immediate
+  3 # . op          subop               mod             rm32          base        index         scale       r32
+  4 # . 1-3 bytes   3 bits              2 bits          3 bits        3 bits      3 bits        2 bits      2 bits      0/1/2/4 bytes   0/1/2/4 bytes
+  5 
+  6 write:  # f: (addr stream byte), s: (addr array byte)
+  7     # . prologue
+  8     55/push-ebp
+  9     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+ 10     # if (s == 0) return
+ 11     81          7/subop/compare     1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       0/imm32           # compare *(ebp+12)
+ 12     74/jump-if-=  $write:end/disp8
+ 13     # TODO: write to file
+ 14     # otherwise, treat 'f' as a stream to append to
+ 15     # . save registers
+ 16     50/push-eax
+ 17     51/push-ecx
+ 18     52/push-edx
+ 19     53/push-ebx
+ 20     # ecx = f
+ 21     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .                         1/r32/ecx   8/disp8         .                 # copy *(ebp+8) to ecx
+ 22     # edx = f->write
+ 23     8b/copy                         0/mod/indirect  1/rm32/ecx    .           .             .           2/r32/edx   .               .                 # copy *ecx to edx
+ 24     # ebx = f->size
+ 25     8b/copy                         1/mod/*+disp8   1/rm32/ecx    .           .             .           3/r32/ebx   8/disp8         .                 # copy *(ecx+8) to ebx
+ 26     # eax = _append-3(&f->data[f->write], &f->data[f->size], s)
+ 27     # . . push s
+ 28     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
+ 29     # . . push &f->data[f->size]
+ 30     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    1/base/ecx  3/index/ebx   .           3/r32/ebx   0xc/disp8       .                 # copy ecx+ebx+12 to ebx
+ 31     53/push-ebx
+ 32     # . . push &f->data[f->write]
+ 33     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    1/base/ecx  2/index/edx   .           3/r32/ebx   0xc/disp8       .                 # copy ecx+edx+12 to ebx
+ 34     53/push-ebx
+ 35     # . . call
+ 36     e8/call  _append-3/disp32
+ 37     # . . discard args
+ 38     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+ 39     # f->write += eax
+ 40     01/add                          0/mod/indirect  1/rm32/ecx    .           .             .           0/r32/eax   .               .                 # add eax to *ecx
+ 41     # . restore registers
+ 42     5b/pop-to-ebx
+ 43     5a/pop-to-edx
+ 44     59/pop-to-ecx
+ 45     58/pop-to-eax
+ 46 $write:end:
+ 47     # . epilogue
+ 48     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+ 49     5d/pop-to-ebp
+ 50     c3/return
+ 51 
+ 52 # TODO: bring in tests once we have check-ints-equal
+ 53 
+ 54 # 3-argument variant of _append
+ 55 _append-3:  # out: (addr byte), outend: (addr byte), s: (addr array byte) -> num_bytes_appended/eax
+ 56     # . prologue
+ 57     55/push-ebp
+ 58     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+ 59     # . save registers
+ 60     51/push-ecx
+ 61     # eax = _append-4(out, outend, &s->data[0], &s->data[s->size])
+ 62     # . . push &s->data[s->size]
+ 63     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .                         0/r32/eax   0x10/disp8      .                 # copy *(ebp+16) to eax
+ 64     8b/copy                         0/mod/indirect  0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # copy *eax to ecx
+ 65     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    0/base/eax  1/index/ecx   .           1/r32/ecx   4/disp8         .                 # copy eax+ecx+4 to ecx
+ 66     51/push-ecx
+ 67     # . . push &s->data[0]
+ 68     8d/copy-address                 1/mod/*+disp8   0/rm32/eax    .           .             .           1/r32/ecx   4/disp8         .                 # copy eax+4 to ecx
+ 69     51/push-ecx
+ 70     # . . push outend
+ 71     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
+ 72     # . . push out
+ 73     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
+ 74     # . . call
+ 75     e8/call  _append-4/disp32
+ 76     # . . discard args
+ 77     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x10/imm32        # add to esp
+ 78 $_append-3:end:
+ 79     # . restore registers
+ 80     59/pop-to-ecx
+ 81     # . epilogue
+ 82     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+ 83     5d/pop-to-ebp
+ 84     c3/return
+ 85 
+ 86 # 4-argument variant of _append
+ 87 _append-4:  # out: (addr byte), outend: (addr byte), in: (addr byte), inend: (addr byte) -> num_bytes_appended/eax: int
+ 88     # . prologue
+ 89     55/push-ebp
+ 90     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+ 91     # . save registers
+ 92     51/push-ecx
+ 93     52/push-edx
+ 94     53/push-ebx
+ 95     56/push-esi
+ 96     57/push-edi
+ 97     # num_bytes_appended = 0
+ 98     b8/copy-to-eax  0/imm32
+ 99     # edi = out
+100     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           7/r32/edi   8/disp8         .                 # copy *(ebp+8) to edi
+101     # edx = outend
+102     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           2/r32/edx   0xc/disp8       .                 # copy *(ebp+12) to edx
+103     # esi = in
+104     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   0x10/disp8      .                 # copy *(ebp+16) to esi
+105     # ecx = inend
+106     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           1/r32/ecx   0x14/disp8      .                 # copy *(ebp+20) to ecx
+107 $_append-4:loop:
+108     # if (in >= inend) break
+109     39/compare                      3/mod/direct    6/rm32/esi    .           .             .           1/r32/ecx   .               .                 # compare esi with ecx
+110     73/jump-if-addr>=  $_append-4:end/disp8
+111     # if (out >= outend) abort  # just to catch test failures fast
+112     39/compare                      3/mod/direct    7/rm32/edi    .           .             .           2/r32/edx   .               .                 # compare edi with edx
+113     73/jump-if-addr>=  $_append-4:end/disp8  # TODO: abort
+114     # *out = *in
+115     8a/copy-byte                    0/mod/indirect  6/rm32/esi    .           .             .           3/r32/BL    .               .                 # copy byte at *esi to BL
+116     88/copy-byte                    0/mod/indirect  7/rm32/edi    .           .             .           3/r32/BL    .               .                 # copy byte at BL to *edi
+117     # ++num_bytes_appended
+118     40/increment-eax
+119     # ++in
+120     46/increment-esi
+121     # ++out
+122     47/increment-edi
+123     eb/jump  $_append-4:loop/disp8
+124 $_append-4:end:
+125     # . restore registers
+126     5f/pop-to-edi
+127     5e/pop-to-esi
+128     5b/pop-to-ebx
+129     5a/pop-to-edx
+130     59/pop-to-ecx
+131     # . epilogue
+132     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+133     5d/pop-to-ebp
+134     c3/return
+135 
+136 # . . vim:nowrap:textwidth=0
 
diff --git a/html/baremetal/112read-byte.subx.html b/html/baremetal/112read-byte.subx.html index 06271ee0..553a564c 100644 --- a/html/baremetal/112read-byte.subx.html +++ b/html/baremetal/112read-byte.subx.html @@ -56,43 +56,44 @@ if ('onhashchange' in window) { https://github.com/akkartik/mu/blob/main/baremetal/112read-byte.subx
- 1 #   instruction                     effective address                                                   register    displacement    immediate
- 2 # . op          subop               mod             rm32          base        index         scale       r32
- 3 # . 1-3 bytes   3 bits              2 bits          3 bits        3 bits      3 bits        2 bits      2 bits      0/1/2/4 bytes   0/1/2/4 bytes
- 4 
- 5 # TODO: read-byte-buffered
- 6 
- 7 # Return next byte value in eax, with top 3 bytes cleared.
- 8 # Abort on reaching end of stream.
- 9 read-byte:  # s: (addr stream byte) -> result/eax: byte
-10     # . prologue
-11     55/push-ebp
-12     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
-13     # . save registers
-14     51/push-ecx
-15     56/push-esi
-16     # esi = s
-17     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   8/disp8         .                 # copy *(ebp+8) to esi
-18     # ecx = s->read
-19     8b/copy                         1/mod/*+disp8   6/rm32/esi    .           .             .           1/r32/ecx   4/disp8         .                 # copy *(esi+4) to ecx
-20     # if (f->read >= f->write) abort
-21     3b/compare                      0/mod/indirect  6/rm32/esi    .           .             .           1/r32/ecx   .               .                 # compare ecx with *esi
-22     0f 8d/jump-if->=  $read-byte:end/disp32  # TODO: abort
-23     # result = f->data[f->read]
-24     31/xor                          3/mod/direct    0/rm32/eax    .           .             .           0/r32/eax   .               .                 # clear eax
-25     8a/copy-byte                    1/mod/*+disp8   4/rm32/sib    6/base/esi  1/index/ecx   .           0/r32/AL    0xc/disp8       .                 # copy byte at *(esi+ecx+12) to AL
-26     # ++f->read
-27     ff          0/subop/increment   1/mod/*+disp8   6/rm32/esi    .           .             .           .           4/disp8         .                 # increment *(esi+4)
-28 $read-byte:end:
-29     # . restore registers
-30     5e/pop-to-esi
-31     59/pop-to-ecx
-32     # . epilogue
-33     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
-34     5d/pop-to-ebp
-35     c3/return
-36 
-37 # . . vim:nowrap:textwidth=0
+ 1 == code
+ 2 #   instruction                     effective address                                                   register    displacement    immediate
+ 3 # . op          subop               mod             rm32          base        index         scale       r32
+ 4 # . 1-3 bytes   3 bits              2 bits          3 bits        3 bits      3 bits        2 bits      2 bits      0/1/2/4 bytes   0/1/2/4 bytes
+ 5 
+ 6 # TODO: read-byte-buffered
+ 7 
+ 8 # Return next byte value in eax, with top 3 bytes cleared.
+ 9 # Abort on reaching end of stream.
+10 read-byte:  # s: (addr stream byte) -> result/eax: byte
+11     # . prologue
+12     55/push-ebp
+13     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+14     # . save registers
+15     51/push-ecx
+16     56/push-esi
+17     # esi = s
+18     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   8/disp8         .                 # copy *(ebp+8) to esi
+19     # ecx = s->read
+20     8b/copy                         1/mod/*+disp8   6/rm32/esi    .           .             .           1/r32/ecx   4/disp8         .                 # copy *(esi+4) to ecx
+21     # if (f->read >= f->write) abort
+22     3b/compare                      0/mod/indirect  6/rm32/esi    .           .             .           1/r32/ecx   .               .                 # compare ecx with *esi
+23     0f 8d/jump-if->=  $read-byte:end/disp32  # TODO: abort
+24     # result = f->data[f->read]
+25     31/xor                          3/mod/direct    0/rm32/eax    .           .             .           0/r32/eax   .               .                 # clear eax
+26     8a/copy-byte                    1/mod/*+disp8   4/rm32/sib    6/base/esi  1/index/ecx   .           0/r32/AL    0xc/disp8       .                 # copy byte at *(esi+ecx+12) to AL
+27     # ++f->read
+28     ff          0/subop/increment   1/mod/*+disp8   6/rm32/esi    .           .             .           .           4/disp8         .                 # increment *(esi+4)
+29 $read-byte:end:
+30     # . restore registers
+31     5e/pop-to-esi
+32     59/pop-to-ecx
+33     # . epilogue
+34     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+35     5d/pop-to-ebp
+36     c3/return
+37 
+38 # . . vim:nowrap:textwidth=0
 
diff --git a/html/baremetal/115write-byte.subx.html b/html/baremetal/115write-byte.subx.html index 7bcd8a8a..1a23343f 100644 --- a/html/baremetal/115write-byte.subx.html +++ b/html/baremetal/115write-byte.subx.html @@ -56,43 +56,44 @@ if ('onhashchange' in window) { https://github.com/akkartik/mu/blob/main/baremetal/115write-byte.subx
- 1 #   instruction                     effective address                                                   register    displacement    immediate
- 2 # . op          subop               mod             rm32          base        index         scale       r32
- 3 # . 1-3 bytes   3 bits              2 bits          3 bits        3 bits      3 bits        2 bits      2 bits      0/1/2/4 bytes   0/1/2/4 bytes
- 4 
- 5 # Write lower byte of 'n' to 'f'.
- 6 append-byte:  # f: (addr stream byte), n: int
- 7     # . prologue
- 8     55/push-ebp
- 9     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
-10     # . save registers
-11     51/push-ecx
-12     57/push-edi
-13     # edi = f
-14     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           7/r32/edi   8/disp8         .                 # copy *(ebp+8) to edi
-15     # ecx = f->write
-16     8b/copy                         0/mod/indirect  7/rm32/edi    .           .             .           1/r32/ecx   .               .                 # copy *edi to ecx
-17     # if (f->write >= f->size) abort
-18     3b/compare                      1/mod/*+disp8   7/rm32/edi    .           .             .           1/r32/ecx   8/disp8         .                 # compare ecx with *(edi+8)
-19     7d/jump-if->=  $append-byte:end/disp8  # TODO: abort
-20 $append-byte:to-stream:
-21     # write to stream
-22     # f->data[f->write] = LSB(n)
-23     31/xor                          3/mod/direct    0/rm32/eax    .           .             .           0/r32/eax   .               .                 # clear eax
-24     8a/copy-byte                    1/mod/*+disp8   5/rm32/ebp    .           .             .           0/r32/AL    0xc/disp8       .                 # copy byte at *(ebp+12) to AL
-25     88/copy-byte                    1/mod/*+disp8   4/rm32/sib    7/base/edi  1/index/ecx   .           0/r32/AL    0xc/disp8       .                 # copy AL to *(edi+ecx+12)
-26     # ++f->write
-27     ff          0/subop/increment   0/mod/indirect  7/rm32/edi    .           .             .           .           .               .                 # increment *edi
-28 $append-byte:end:
-29     # . restore registers
-30     5f/pop-to-edi
-31     59/pop-to-ecx
-32     # . epilogue
-33     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
-34     5d/pop-to-ebp
-35     c3/return
-36 
-37 # . . vim:nowrap:textwidth=0
+ 1 == code
+ 2 #   instruction                     effective address                                                   register    displacement    immediate
+ 3 # . op          subop               mod             rm32          base        index         scale       r32
+ 4 # . 1-3 bytes   3 bits              2 bits          3 bits        3 bits      3 bits        2 bits      2 bits      0/1/2/4 bytes   0/1/2/4 bytes
+ 5 
+ 6 # Write lower byte of 'n' to 'f'.
+ 7 append-byte:  # f: (addr stream byte), n: int
+ 8     # . prologue
+ 9     55/push-ebp
+10     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+11     # . save registers
+12     51/push-ecx
+13     57/push-edi
+14     # edi = f
+15     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           7/r32/edi   8/disp8         .                 # copy *(ebp+8) to edi
+16     # ecx = f->write
+17     8b/copy                         0/mod/indirect  7/rm32/edi    .           .             .           1/r32/ecx   .               .                 # copy *edi to ecx
+18     # if (f->write >= f->size) abort
+19     3b/compare                      1/mod/*+disp8   7/rm32/edi    .           .             .           1/r32/ecx   8/disp8         .                 # compare ecx with *(edi+8)
+20     7d/jump-if->=  $append-byte:end/disp8  # TODO: abort
+21 $append-byte:to-stream:
+22     # write to stream
+23     # f->data[f->write] = LSB(n)
+24     31/xor                          3/mod/direct    0/rm32/eax    .           .             .           0/r32/eax   .               .                 # clear eax
+25     8a/copy-byte                    1/mod/*+disp8   5/rm32/ebp    .           .             .           0/r32/AL    0xc/disp8       .                 # copy byte at *(ebp+12) to AL
+26     88/copy-byte                    1/mod/*+disp8   4/rm32/sib    7/base/edi  1/index/ecx   .           0/r32/AL    0xc/disp8       .                 # copy AL to *(edi+ecx+12)
+27     # ++f->write
+28     ff          0/subop/increment   0/mod/indirect  7/rm32/edi    .           .             .           .           .               .                 # increment *edi
+29 $append-byte:end:
+30     # . restore registers
+31     5f/pop-to-edi
+32     59/pop-to-ecx
+33     # . epilogue
+34     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+35     5d/pop-to-ebp
+36     c3/return
+37 
+38 # . . vim:nowrap:textwidth=0
 
diff --git a/html/baremetal/120allocate.subx.html b/html/baremetal/120allocate.subx.html index 11c874ee..d3bc3fc8 100644 --- a/html/baremetal/120allocate.subx.html +++ b/html/baremetal/120allocate.subx.html @@ -56,58 +56,59 @@ if ('onhashchange' in window) { https://github.com/akkartik/mu/blob/main/baremetal/120allocate.subx
- 1 #   instruction                     effective address                                                   register    displacement    immediate
- 2 # . op          subop               mod             rm32          base        index         scale       r32
- 3 # . 1-3 bytes   3 bits              2 bits          3 bits        3 bits      3 bits        2 bits      2 bits      0/1/2/4 bytes   0/1/2/4 bytes
- 4 
- 5 # Fill a region of memory with zeroes.
- 6 zero-out:  # start: (addr byte), size: int
- 7     # pseudocode:
- 8     #   curr/esi = start
- 9     #   i/ecx = 0
-10     #   while true
-11     #     if (i >= size) break
-12     #     *curr = 0
-13     #     ++curr
-14     #     ++i
-15     #
-16     # . prologue
-17     55/push-ebp
-18     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
-19     # . save registers
-20     50/push-eax
-21     51/push-ecx
-22     52/push-edx
-23     56/push-esi
-24     # curr/esi = start
-25     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   8/disp8         .                 # copy *(ebp+8) to esi
-26     # var i/ecx: int = 0
-27     31/xor                          3/mod/direct    1/rm32/ecx    .           .             .           1/r32/ecx   .               .                 # clear ecx
-28     # edx = size
-29     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           2/r32/edx   0xc/disp8       .                 # copy *(ebp+12) to edx
-30 $zero-out:loop:
-31     # if (i >= size) break
-32     39/compare                      3/mod/direct    1/rm32/ecx    .           .             .           2/r32/edx   .               .                 # compare ecx with edx
-33     7d/jump-if->=  $zero-out:end/disp8
-34     # *curr = 0
-35     c6          0/subop/copy-byte   0/mod/direct    6/rm32/esi    .           .             .           .           .               0/imm8            # copy byte to *esi
-36     # ++curr
-37     46/increment-esi
-38     # ++i
-39     41/increment-ecx
-40     eb/jump  $zero-out:loop/disp8
-41 $zero-out:end:
-42     # . restore registers
-43     5e/pop-to-esi
-44     5a/pop-to-edx
-45     59/pop-to-ecx
-46     58/pop-to-eax
-47     # . epilogue
-48     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
-49     5d/pop-to-ebp
-50     c3/return
-51 
-52 # . . vim:nowrap:textwidth=0
+ 1 == code
+ 2 #   instruction                     effective address                                                   register    displacement    immediate
+ 3 # . op          subop               mod             rm32          base        index         scale       r32
+ 4 # . 1-3 bytes   3 bits              2 bits          3 bits        3 bits      3 bits        2 bits      2 bits      0/1/2/4 bytes   0/1/2/4 bytes
+ 5 
+ 6 # Fill a region of memory with zeroes.
+ 7 zero-out:  # start: (addr byte), size: int
+ 8     # pseudocode:
+ 9     #   curr/esi = start
+10     #   i/ecx = 0
+11     #   while true
+12     #     if (i >= size) break
+13     #     *curr = 0
+14     #     ++curr
+15     #     ++i
+16     #
+17     # . prologue
+18     55/push-ebp
+19     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+20     # . save registers
+21     50/push-eax
+22     51/push-ecx
+23     52/push-edx
+24     56/push-esi
+25     # curr/esi = start
+26     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   8/disp8         .                 # copy *(ebp+8) to esi
+27     # var i/ecx: int = 0
+28     31/xor                          3/mod/direct    1/rm32/ecx    .           .             .           1/r32/ecx   .               .                 # clear ecx
+29     # edx = size
+30     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           2/r32/edx   0xc/disp8       .                 # copy *(ebp+12) to edx
+31 $zero-out:loop:
+32     # if (i >= size) break
+33     39/compare                      3/mod/direct    1/rm32/ecx    .           .             .           2/r32/edx   .               .                 # compare ecx with edx
+34     7d/jump-if->=  $zero-out:end/disp8
+35     # *curr = 0
+36     c6          0/subop/copy-byte   0/mod/direct    6/rm32/esi    .           .             .           .           .               0/imm8            # copy byte to *esi
+37     # ++curr
+38     46/increment-esi
+39     # ++i
+40     41/increment-ecx
+41     eb/jump  $zero-out:loop/disp8
+42 $zero-out:end:
+43     # . restore registers
+44     5e/pop-to-esi
+45     5a/pop-to-edx
+46     59/pop-to-ecx
+47     58/pop-to-eax
+48     # . epilogue
+49     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+50     5d/pop-to-ebp
+51     c3/return
+52 
+53 # . . vim:nowrap:textwidth=0
 
diff --git a/html/baremetal/302stack_allocate.subx.html b/html/baremetal/302stack_allocate.subx.html index 0cbbf443..af165122 100644 --- a/html/baremetal/302stack_allocate.subx.html +++ b/html/baremetal/302stack_allocate.subx.html @@ -104,7 +104,7 @@ if ('onhashchange' in window) { 47 89/<- *Push-n-zero-bytes-esp 4/r32/esp 48 81 0/subop/add *Push-n-zero-bytes-esp 4/imm32 49 81 0/subop/add *(ebp+4) 4/imm32 -50 (zero-out *Push-n-zero-bytes-esp *(ebp+4)) # n+4 +50 (zero-out *Push-n-zero-bytes-esp *(ebp+4)) # n+4 51 $push-n-zero-bytes:epilogue: 52 8b/-> *Push-n-zero-bytes-ebp 5/r32/ebp # restore spill 53 c3/return diff --git a/html/baremetal/309stream.subx.html b/html/baremetal/309stream.subx.html index 16e45ed7..3883daba 100644 --- a/html/baremetal/309stream.subx.html +++ b/html/baremetal/309stream.subx.html @@ -137,7 +137,7 @@ if ('onhashchange' in window) { 81 8b/-> *(ebp+0x10) 1/r32/ecx 82 8d/copy-address *(eax+ecx) 1/r32/ecx 83 # - 84 (_append-4 %edx %ebx %eax %ecx) # => eax + 84 (_append-4 %edx %ebx %eax %ecx) # => eax 85 # s->write += n 86 8b/-> *(ebp+0x10) 1/r32/ecx 87 01/add-to *edi 1/r32/ecx @@ -183,7 +183,7 @@ if ('onhashchange' in window) { 127 8b/-> *(ebp+0x10) 1/r32/ecx 128 8d/copy-address *(eax+ecx) 1/r32/ecx 129 # -130 (_append-4 %eax %ecx %edx %ebx) # => eax +130 (_append-4 %eax %ecx %edx %ebx) # => eax 131 # s->read += n 132 8b/-> *(ebp+0x10) 1/r32/ecx 133 01/add-to *(esi+4) 1/r32/ecx diff --git a/html/baremetal/313index-bounds-check.subx.html b/html/baremetal/313index-bounds-check.subx.html index a6421293..2dc4cfc4 100644 --- a/html/baremetal/313index-bounds-check.subx.html +++ b/html/baremetal/313index-bounds-check.subx.html @@ -56,15 +56,17 @@ if ('onhashchange' in window) {
  1 # TODO: bring this back
  2 
- 3 __check-mu-array-bounds:  # index: int, elem-size: int, arr-size: int, function-name: (addr array byte), array-name: (addr array byte)
- 4     # . prologue
- 5     55/push-ebp
- 6     89/<- %ebp 4/r32/esp
- 7 $__check-mu-array-bounds:end:
- 8     # . epilogue
- 9     89/<- %esp 5/r32/ebp
-10     5d/pop-to-ebp
-11     c3/return
+ 3 == code
+ 4 
+ 5 __check-mu-array-bounds:  # index: int, elem-size: int, arr-size: int, function-name: (addr array byte), array-name: (addr array byte)
+ 6     # . prologue
+ 7     55/push-ebp
+ 8     89/<- %ebp 4/r32/esp
+ 9 $__check-mu-array-bounds:end:
+10     # . epilogue
+11     89/<- %esp 5/r32/ebp
+12     5d/pop-to-ebp
+13     c3/return
 
diff --git a/html/baremetal/400.mu.html b/html/baremetal/400.mu.html index 95835ad8..67aed2ec 100644 --- a/html/baremetal/400.mu.html +++ b/html/baremetal/400.mu.html @@ -17,6 +17,7 @@ a { color:inherit; } .PreProc { color: #c000c0; } .LineNr { } .Constant { color: #008787; } +.muComment { color: #005faf; } --> @@ -52,17 +53,26 @@ if ('onhashchange' in window) { https://github.com/akkartik/mu/blob/main/baremetal/400.mu
- 1 sig pixel screen: (addr screen), x: int, y: int, color: int
- 2 sig read-key kbd: (addr keyboard) -> _/eax: byte
- 3 sig draw-grapheme screen: (addr screen), g: grapheme, x: int, y: int, color: int
- 4 sig cursor-position screen: (addr screen) -> _/eax: int, _/ecx: int
- 5 sig set-cursor-position screen: (addr screen), x: int, y: int
- 6 sig clear-stream f: (addr stream _)
- 7 sig rewind-stream f: (addr stream _)
- 8 sig write f: (addr stream byte), s: (addr array byte)
- 9 sig append-byte f: (addr stream byte), n: int
-10 sig read-byte s: (addr stream byte) -> _/eax: byte
-11 sig stream-empty? s: (addr stream _) -> _/eax: boolean
+ 1 # screen
+ 2 sig pixel screen: (addr screen), x: int, y: int, color: int
+ 3 sig draw-grapheme screen: (addr screen), g: grapheme, x: int, y: int, color: int
+ 4 sig cursor-position screen: (addr screen) -> _/eax: int, _/ecx: int
+ 5 sig set-cursor-position screen: (addr screen), x: int, y: int
+ 6 
+ 7 # keyboard
+ 8 sig read-key kbd: (addr keyboard) -> _/eax: byte
+ 9 
+10 # tests
+11 sig count-test-failure
+12 sig num-test-failures -> _/eax: int
+13 
+14 # streams
+15 sig clear-stream f: (addr stream _)
+16 sig rewind-stream f: (addr stream _)
+17 sig write f: (addr stream byte), s: (addr array byte)
+18 sig append-byte f: (addr stream byte), n: int
+19 sig read-byte s: (addr stream byte) -> _/eax: byte
+20 sig stream-empty? s: (addr stream _) -> _/eax: boolean
 
diff --git a/html/baremetal/403unicode.mu.html b/html/baremetal/403unicode.mu.html index b1118a7c..1b70148c 100644 --- a/html/baremetal/403unicode.mu.html +++ b/html/baremetal/403unicode.mu.html @@ -155,7 +155,7 @@ if ('onhashchange' in window) { 97 break-if-= 98 return 0xffffffff 99 } -100 var c/eax: byte <- read-byte in +100 var c/eax: byte <- read-byte in 101 var num-trailers/ecx: int <- copy 0 102 $read-grapheme:compute-length: { 103 # single byte: just return it @@ -201,7 +201,7 @@ if ('onhashchange' in window) { 143 { 144 compare num-trailers, 0 145 break-if-<= -146 var tmp/eax: byte <- read-byte in +146 var tmp/eax: byte <- read-byte in 147 var tmp2/eax: int <- copy tmp 148 tmp2 <- shift-left-bytes tmp2, num-byte-shifts 149 result <- or tmp2 @@ -234,19 +234,19 @@ if ('onhashchange' in window) { 176 fn write-grapheme out: (addr stream byte), g: grapheme { 177 $write-grapheme:body: { 178 var c/eax: int <- copy g -179 append-byte out, c # first byte is always written +179 append-byte out, c # first byte is always written 180 c <- shift-right 8 181 compare c, 0 182 break-if-= $write-grapheme:body -183 append-byte out, c +183 append-byte out, c 184 c <- shift-right 8 185 compare c, 0 186 break-if-= $write-grapheme:body -187 append-byte out, c +187 append-byte out, c 188 c <- shift-right 8 189 compare c, 0 190 break-if-= $write-grapheme:body -191 append-byte out, c +191 append-byte out, c 192 } 193 } diff --git a/html/baremetal/500clear-screen.mu.html b/html/baremetal/500clear-screen.mu.html new file mode 100644 index 00000000..e78089e6 --- /dev/null +++ b/html/baremetal/500clear-screen.mu.html @@ -0,0 +1,79 @@ + + + + +Mu - baremetal/500clear-screen.mu + + + + + + + + + + +https://github.com/akkartik/mu/blob/main/baremetal/500clear-screen.mu +
+ 1 fn clear-screen screen: (addr screen) {
+ 2   var y/eax: int <- copy 0
+ 3   {
+ 4     compare y, 0x300  # 768
+ 5     break-if->=
+ 6     var x/edx: int <- copy 0
+ 7     {
+ 8       compare x, 0x400  # 1024
+ 9       break-if->=
+10       pixel 0, x, y, 0  # black
+11       x <- increment
+12       loop
+13     }
+14     y <- increment
+15     loop
+16   }
+17 }
+
+ + + diff --git a/html/baremetal/501draw-text.mu.html b/html/baremetal/501draw-text.mu.html index c877d08d..d57d46cb 100644 --- a/html/baremetal/501draw-text.mu.html +++ b/html/baremetal/501draw-text.mu.html @@ -61,60 +61,60 @@ if ('onhashchange' in window) { 3 fn cursor-left screen: (addr screen) { 4 var cursor-x/eax: int <- copy 0 5 var cursor-y/ecx: int <- copy 0 - 6 cursor-x, cursor-y <- cursor-position screen + 6 cursor-x, cursor-y <- cursor-position screen 7 compare cursor-x, 0 8 { 9 break-if-> 10 return 11 } 12 cursor-x <- subtract 8 # font-width - 13 set-cursor-position screen, cursor-x, cursor-y + 13 set-cursor-position screen, cursor-x, cursor-y 14 } 15 16 fn cursor-right screen: (addr screen) { 17 var cursor-x/eax: int <- copy 0 18 var cursor-y/ecx: int <- copy 0 - 19 cursor-x, cursor-y <- cursor-position screen + 19 cursor-x, cursor-y <- cursor-position screen 20 compare cursor-x, 0x400 # screen-width 21 { 22 break-if-< 23 return 24 } 25 cursor-x <- add 8 # font-width - 26 set-cursor-position screen, cursor-x, cursor-y + 26 set-cursor-position screen, cursor-x, cursor-y 27 } 28 29 fn cursor-up screen: (addr screen) { 30 var cursor-x/eax: int <- copy 0 31 var cursor-y/ecx: int <- copy 0 - 32 cursor-x, cursor-y <- cursor-position screen + 32 cursor-x, cursor-y <- cursor-position screen 33 compare cursor-y, 0 34 { 35 break-if-> 36 return 37 } 38 cursor-y <- subtract 0x10 # screen-height - 39 set-cursor-position screen, cursor-x, cursor-y + 39 set-cursor-position screen, cursor-x, cursor-y 40 } 41 42 fn cursor-down screen: (addr screen) { 43 var cursor-x/eax: int <- copy 0 44 var cursor-y/ecx: int <- copy 0 - 45 cursor-x, cursor-y <- cursor-position screen + 45 cursor-x, cursor-y <- cursor-position screen 46 compare cursor-y, 0x300 # screen-height 47 { 48 break-if-< 49 return 50 } 51 cursor-y <- add 0x10 # screen-height - 52 set-cursor-position screen, cursor-x, cursor-y + 52 set-cursor-position screen, cursor-x, cursor-y 53 } 54 55 fn draw-grapheme-at-cursor screen: (addr screen), g: grapheme, color: int { 56 var cursor-x/eax: int <- copy 0 57 var cursor-y/ecx: int <- copy 0 - 58 cursor-x, cursor-y <- cursor-position screen - 59 draw-grapheme screen, g, cursor-x, cursor-y, color + 58 cursor-x, cursor-y <- cursor-position screen + 59 draw-grapheme screen, g, cursor-x, cursor-y, color 60 } 61 62 # draw a single line of text from x, y to xmax @@ -123,7 +123,7 @@ if ('onhashchange' in window) { 65 fn draw-text-rightward screen: (addr screen), text: (addr array byte), x: int, xmax: int, y: int, color: int -> _/eax: int { 66 var stream-storage: (stream byte 0x100) 67 var stream/esi: (addr stream byte) <- address stream-storage - 68 write stream, text + 68 write stream, text 69 # check if we have enough space 70 var xcurr/ecx: int <- copy x 71 { @@ -147,18 +147,18 @@ if ('onhashchange' in window) { 89 var g/eax: grapheme <- read-grapheme stream 90 compare g, 0xffffffff # end-of-file 91 break-if-= - 92 draw-grapheme screen, g, xcurr, y, color + 92 draw-grapheme screen, g, xcurr, y, color 93 xcurr <- add 8 # font-width 94 loop 95 } - 96 set-cursor-position screen, xcurr, y + 96 set-cursor-position screen, xcurr, y 97 return xcurr 98 } 99 100 fn draw-text-rightward-from-cursor screen: (addr screen), text: (addr array byte), xmax: int, color: int -> _/eax: int { 101 var cursor-x/eax: int <- copy 0 102 var cursor-y/ecx: int <- copy 0 -103 cursor-x, cursor-y <- cursor-position screen +103 cursor-x, cursor-y <- cursor-position screen 104 var result/eax: int <- draw-text-rightward screen, text, cursor-x, xmax, cursor-y, color 105 return result 106 } @@ -170,7 +170,7 @@ if ('onhashchange' in window) { 112 fn draw-text-wrapping-right-then-down screen: (addr screen), text: (addr array byte), xmin: int, ymin: int, xmax: int, ymax: int, x: int, y: int, color: int -> _/eax: int, _/ecx: int { 113 var stream-storage: (stream byte 0x100) 114 var stream/esi: (addr stream byte) <- address stream-storage -115 write stream, text +115 write stream, text 116 # check if we have enough space 117 var xcurr/edx: int <- copy x 118 var ycurr/ecx: int <- copy y @@ -202,7 +202,7 @@ if ('onhashchange' in window) { 144 var g/eax: grapheme <- read-grapheme stream 145 compare g, 0xffffffff # end-of-file 146 break-if-= -147 draw-grapheme screen, g, xcurr, ycurr, color +147 draw-grapheme screen, g, xcurr, ycurr, color 148 xcurr <- add 8 # font-width 149 compare xcurr, xmax 150 { @@ -212,7 +212,7 @@ if ('onhashchange' in window) { 154 } 155 loop 156 } -157 set-cursor-position screen, xcurr, ycurr +157 set-cursor-position screen, xcurr, ycurr 158 return xcurr, ycurr 159 } 160 @@ -223,10 +223,10 @@ if ('onhashchange' in window) { 165 return cursor-x, cursor-y 166 } 167 -168 fn draw-text-wrapping-right-then-down-from-cursor screen: (addr screen), text: (addr array byte), xmin: int, ymin: int, xmax: int, ymax: int, color: int -> _/eax: int, _/ecx: int { +168 fn draw-text-wrapping-right-then-down-from-cursor screen: (addr screen), text: (addr array byte), xmin: int, ymin: int, xmax: int, ymax: int, color: int { 169 var cursor-x/eax: int <- copy 0 170 var cursor-y/ecx: int <- copy 0 -171 cursor-x, cursor-y <- cursor-position screen +171 cursor-x, cursor-y <- cursor-position screen 172 var end-x/edx: int <- copy cursor-x 173 end-x <- add 8 # font-width 174 compare end-x, xmax @@ -236,146 +236,137 @@ if ('onhashchange' in window) { 178 cursor-y <- add 0x10 # font-height 179 } 180 cursor-x, cursor-y <- draw-text-wrapping-right-then-down screen, text, xmin, ymin, xmax, ymax, cursor-x, cursor-y, color -181 return cursor-x, cursor-y -182 } -183 -184 fn draw-text-wrapping-right-then-down-from-cursor-over-full-screen screen: (addr screen), text: (addr array byte), color: int -> _/eax: int, _/ecx: int { -185 var cursor-x/eax: int <- copy 0 -186 var cursor-y/ecx: int <- copy 0 -187 cursor-x, cursor-y <- draw-text-wrapping-right-then-down-from-cursor screen, text, 0, 0, 0x400, 0x300, color # 1024, 768 -188 return cursor-x, cursor-y -189 } -190 -191 ## Text direction: down then right -192 -193 # draw a single line of text vertically from x, y to ymax -194 # return the next 'y' coordinate -195 # if there isn't enough space, return 0 without modifying the screen -196 fn draw-text-downward screen: (addr screen), text: (addr array byte), x: int, y: int, ymax: int, color: int -> _/eax: int { -197 var stream-storage: (stream byte 0x100) -198 var stream/esi: (addr stream byte) <- address stream-storage -199 write stream, text -200 # check if we have enough space -201 var ycurr/ecx: int <- copy y -202 { -203 compare ycurr, ymax -204 break-if-> -205 var g/eax: grapheme <- read-grapheme stream -206 compare g, 0xffffffff # end-of-file -207 break-if-= -208 ycurr <- add 0x10 # font-height -209 loop -210 } -211 compare ycurr, ymax -212 { -213 break-if-<= -214 return 0 -215 } -216 # we do; actually draw -217 rewind-stream stream -218 ycurr <- copy y -219 { -220 var g/eax: grapheme <- read-grapheme stream -221 compare g, 0xffffffff # end-of-file -222 break-if-= -223 draw-grapheme screen, g, x, ycurr, color -224 ycurr <- add 0x10 # font-height -225 loop -226 } -227 set-cursor-position screen, x, ycurr -228 return ycurr -229 } -230 -231 fn draw-text-downward-from-cursor screen: (addr screen), text: (addr array byte), ymax: int, color: int -> _/eax: int { -232 var cursor-x/eax: int <- copy 0 -233 var cursor-y/ecx: int <- copy 0 -234 cursor-x, cursor-y <- cursor-position screen -235 var result/eax: int <- draw-text-downward screen, text, cursor-x, cursor-y, ymax, color -236 return result -237 } -238 -239 # draw text down and right in the rectangle from (xmin, ymin) to (xmax, ymax), starting from (x, y), wrapping as necessary -240 # return the next (x, y) coordinate in raster order where drawing stopped -241 # that way the caller can draw more if given the same min and max bounding-box. -242 # if there isn't enough space, return 0 without modifying the screen -243 fn draw-text-wrapping-down-then-right screen: (addr screen), text: (addr array byte), xmin: int, ymin: int, xmax: int, ymax: int, x: int, y: int, color: int -> _/eax: int, _/ecx: int { -244 var stream-storage: (stream byte 0x100) -245 var stream/esi: (addr stream byte) <- address stream-storage -246 write stream, text -247 # check if we have enough space -248 var xcurr/edx: int <- copy x -249 var ycurr/ecx: int <- copy y -250 { -251 compare xcurr, xmax -252 break-if->= -253 var g/eax: grapheme <- read-grapheme stream -254 compare g, 0xffffffff # end-of-file -255 break-if-= -256 ycurr <- add 0x10 # font-height -257 compare ycurr, ymax -258 { -259 break-if-< -260 xcurr <- add 8 # font-width -261 ycurr <- copy ymin -262 } -263 loop +181 } +182 +183 fn draw-text-wrapping-right-then-down-from-cursor-over-full-screen screen: (addr screen), text: (addr array byte), color: int { +184 draw-text-wrapping-right-then-down-from-cursor screen, text, 0, 0, 0x400, 0x300, color # 1024, 768 +185 } +186 +187 ## Text direction: down then right +188 +189 # draw a single line of text vertically from x, y to ymax +190 # return the next 'y' coordinate +191 # if there isn't enough space, return 0 without modifying the screen +192 fn draw-text-downward screen: (addr screen), text: (addr array byte), x: int, y: int, ymax: int, color: int -> _/eax: int { +193 var stream-storage: (stream byte 0x100) +194 var stream/esi: (addr stream byte) <- address stream-storage +195 write stream, text +196 # check if we have enough space +197 var ycurr/ecx: int <- copy y +198 { +199 compare ycurr, ymax +200 break-if-> +201 var g/eax: grapheme <- read-grapheme stream +202 compare g, 0xffffffff # end-of-file +203 break-if-= +204 ycurr <- add 0x10 # font-height +205 loop +206 } +207 compare ycurr, ymax +208 { +209 break-if-<= +210 return 0 +211 } +212 # we do; actually draw +213 rewind-stream stream +214 ycurr <- copy y +215 { +216 var g/eax: grapheme <- read-grapheme stream +217 compare g, 0xffffffff # end-of-file +218 break-if-= +219 draw-grapheme screen, g, x, ycurr, color +220 ycurr <- add 0x10 # font-height +221 loop +222 } +223 set-cursor-position screen, x, ycurr +224 return ycurr +225 } +226 +227 fn draw-text-downward-from-cursor screen: (addr screen), text: (addr array byte), ymax: int, color: int { +228 var cursor-x/eax: int <- copy 0 +229 var cursor-y/ecx: int <- copy 0 +230 cursor-x, cursor-y <- cursor-position screen +231 var result/eax: int <- draw-text-downward screen, text, cursor-x, cursor-y, ymax, color +232 } +233 +234 # draw text down and right in the rectangle from (xmin, ymin) to (xmax, ymax), starting from (x, y), wrapping as necessary +235 # return the next (x, y) coordinate in raster order where drawing stopped +236 # that way the caller can draw more if given the same min and max bounding-box. +237 # if there isn't enough space, return 0 without modifying the screen +238 fn draw-text-wrapping-down-then-right screen: (addr screen), text: (addr array byte), xmin: int, ymin: int, xmax: int, ymax: int, x: int, y: int, color: int -> _/eax: int, _/ecx: int { +239 var stream-storage: (stream byte 0x100) +240 var stream/esi: (addr stream byte) <- address stream-storage +241 write stream, text +242 # check if we have enough space +243 var xcurr/edx: int <- copy x +244 var ycurr/ecx: int <- copy y +245 { +246 compare xcurr, xmax +247 break-if->= +248 var g/eax: grapheme <- read-grapheme stream +249 compare g, 0xffffffff # end-of-file +250 break-if-= +251 ycurr <- add 0x10 # font-height +252 compare ycurr, ymax +253 { +254 break-if-< +255 xcurr <- add 8 # font-width +256 ycurr <- copy ymin +257 } +258 loop +259 } +260 compare xcurr, xmax +261 { +262 break-if-< +263 return 0, 0 264 } -265 compare xcurr, xmax -266 { -267 break-if-< -268 return 0, 0 -269 } -270 # we do; actually draw -271 rewind-stream stream -272 xcurr <- copy x -273 ycurr <- copy y -274 { -275 var g/eax: grapheme <- read-grapheme stream -276 compare g, 0xffffffff # end-of-file -277 break-if-= -278 draw-grapheme screen, g, xcurr, ycurr, color -279 ycurr <- add 0x10 # font-height -280 compare ycurr, ymax -281 { -282 break-if-< -283 xcurr <- add 8 # font-width -284 ycurr <- copy ymin -285 } -286 loop -287 } -288 set-cursor-position screen, xcurr, ycurr -289 return xcurr, ycurr -290 } -291 -292 fn draw-text-wrapping-down-then-right-over-full-screen screen: (addr screen), text: (addr array byte), x: int, y: int, color: int -> _/eax: int, _/ecx: int { -293 var cursor-x/eax: int <- copy 0 -294 var cursor-y/ecx: int <- copy 0 -295 cursor-x, cursor-y <- draw-text-wrapping-down-then-right screen, text, 0, 0, 0x400, 0x300, x, y, color # 1024, 768 -296 return cursor-x, cursor-y -297 } -298 -299 fn draw-text-wrapping-down-then-right-from-cursor screen: (addr screen), text: (addr array byte), xmin: int, ymin: int, xmax: int, ymax: int, color: int -> _/eax: int, _/ecx: int { -300 var cursor-x/eax: int <- copy 0 -301 var cursor-y/ecx: int <- copy 0 -302 cursor-x, cursor-y <- cursor-position screen -303 var end-y/edx: int <- copy cursor-y -304 end-y <- add 0x10 # font-height -305 compare end-y, ymax -306 { -307 break-if-< -308 cursor-x <- add 8 # font-width -309 cursor-y <- copy ymin -310 } -311 cursor-x, cursor-y <- draw-text-wrapping-down-then-right screen, text, xmin, ymin, xmax, ymax, cursor-x, cursor-y, color -312 return cursor-x, cursor-y -313 } -314 -315 fn draw-text-wrapping-down-then-right-from-cursor-over-full-screen screen: (addr screen), text: (addr array byte), color: int -> _/eax: int, _/ecx: int { -316 var cursor-x/eax: int <- copy 0 -317 var cursor-y/ecx: int <- copy 0 -318 cursor-x, cursor-y <- draw-text-wrapping-down-then-right-from-cursor screen, text, 0, 0, 0x400, 0x300, color # 1024, 768 -319 return cursor-x, cursor-y -320 } +265 # we do; actually draw +266 rewind-stream stream +267 xcurr <- copy x +268 ycurr <- copy y +269 { +270 var g/eax: grapheme <- read-grapheme stream +271 compare g, 0xffffffff # end-of-file +272 break-if-= +273 draw-grapheme screen, g, xcurr, ycurr, color +274 ycurr <- add 0x10 # font-height +275 compare ycurr, ymax +276 { +277 break-if-< +278 xcurr <- add 8 # font-width +279 ycurr <- copy ymin +280 } +281 loop +282 } +283 set-cursor-position screen, xcurr, ycurr +284 return xcurr, ycurr +285 } +286 +287 fn draw-text-wrapping-down-then-right-over-full-screen screen: (addr screen), text: (addr array byte), x: int, y: int, color: int -> _/eax: int, _/ecx: int { +288 var cursor-x/eax: int <- copy 0 +289 var cursor-y/ecx: int <- copy 0 +290 cursor-x, cursor-y <- draw-text-wrapping-down-then-right screen, text, 0, 0, 0x400, 0x300, x, y, color # 1024, 768 +291 return cursor-x, cursor-y +292 } +293 +294 fn draw-text-wrapping-down-then-right-from-cursor screen: (addr screen), text: (addr array byte), xmin: int, ymin: int, xmax: int, ymax: int, color: int { +295 var cursor-x/eax: int <- copy 0 +296 var cursor-y/ecx: int <- copy 0 +297 cursor-x, cursor-y <- cursor-position screen +298 var end-y/edx: int <- copy cursor-y +299 end-y <- add 0x10 # font-height +300 compare end-y, ymax +301 { +302 break-if-< +303 cursor-x <- add 8 # font-width +304 cursor-y <- copy ymin +305 } +306 cursor-x, cursor-y <- draw-text-wrapping-down-then-right screen, text, xmin, ymin, xmax, ymax, cursor-x, cursor-y, color +307 } +308 +309 fn draw-text-wrapping-down-then-right-from-cursor-over-full-screen screen: (addr screen), text: (addr array byte), color: int { +310 draw-text-wrapping-down-then-right-from-cursor screen, text, 0, 0, 0x400, 0x300, color # 1024, 768 +311 } diff --git a/html/baremetal/502test.mu.html b/html/baremetal/502test.mu.html new file mode 100644 index 00000000..f1bf0f28 --- /dev/null +++ b/html/baremetal/502test.mu.html @@ -0,0 +1,82 @@ + + + + +Mu - baremetal/502test.mu + + + + + + + + + + +https://github.com/akkartik/mu/blob/main/baremetal/502test.mu +
+ 1 # print msg to screen if a != b, otherwise print "."
+ 2 fn check-ints-equal _a: int, b: int, msg: (addr array byte) {
+ 3   var a/eax: int <- copy _a
+ 4   compare a, b
+ 5   {
+ 6     break-if-=
+ 7     draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0, msg, 3  # 3=cyan
+ 8     count-test-failure
+ 9     return
+10   }
+11   {
+12     break-if-!=
+13     draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0, ".", 3  # 3=cyan
+14   }
+15 }
+16 
+17 fn test-check-ints-equal {
+18   check-ints-equal 0, 0, "abc"
+19 }
+
+ + + diff --git a/html/baremetal/503manhattan-line.mu.html b/html/baremetal/503manhattan-line.mu.html index bb47dd36..916b6f67 100644 --- a/html/baremetal/503manhattan-line.mu.html +++ b/html/baremetal/503manhattan-line.mu.html @@ -67,7 +67,7 @@ if ('onhashchange' in window) { 10 { 11 compare x, x2 12 break-if->= -13 pixel screen, x, y, color +13 pixel screen, x, y, color 14 x <- increment 15 loop 16 } @@ -78,7 +78,7 @@ if ('onhashchange' in window) { 21 { 22 compare y, y2 23 break-if->= -24 pixel screen, x, y, color +24 pixel screen, x, y, color 25 y <- increment 26 loop 27 } diff --git a/html/baremetal/ex1.subx.html b/html/baremetal/ex1.subx.html index dca74155..124ce287 100644 --- a/html/baremetal/ex1.subx.html +++ b/html/baremetal/ex1.subx.html @@ -64,10 +64,12 @@ if ('onhashchange' in window) { 10 # Or: 11 # bochs -f baremetal/boot.bochsrc # boot.bochsrc loads disk.img 12 -13 main: -14 e9/jump main/disp32 -15 -16 # vim:ft=subx +13 == code +14 +15 main: +16 e9/jump main/disp32 +17 +18 # vim:ft=subx diff --git a/html/baremetal/ex2.mu.html b/html/baremetal/ex2.mu.html index a0f4508d..dc700ce5 100644 --- a/html/baremetal/ex2.mu.html +++ b/html/baremetal/ex2.mu.html @@ -79,7 +79,7 @@ if ('onhashchange' in window) { 21 break-if->= 22 var color/ecx: int <- copy x 23 color <- and 0xff -24 pixel 0, x, y, color +24 pixel 0, x, y, color 25 x <- increment 26 loop 27 } diff --git a/html/baremetal/ex2.subx.html b/html/baremetal/ex2.subx.html index 3d27392c..9064d31b 100644 --- a/html/baremetal/ex2.subx.html +++ b/html/baremetal/ex2.subx.html @@ -65,27 +65,29 @@ if ('onhashchange' in window) { 10 # Expected output: 11 # html/baremetal.png 12 -13 main: -14 # ecx <- start of video memory -15 8b/-> *0x7f28 1/r32/ecx -16 -17 # eax <- final pixel of video memory -18 8d/copy-address *(ecx + 0x0bffff) 0/r32/eax # 0xbffff = 1024*768 - 1 -19 -20 # for each pixel in video memory -21 { -22 39/compare %eax 1/r32/ecx -23 7c/jump-if-< break/disp8 -24 # write its column number to it -25 88/byte<- *eax 0/r32/AL -26 48/decrement-eax -27 eb/jump loop/disp8 -28 } -29 -30 # hang indefinitely -31 { -32 eb/jump loop/disp8 -33 } +13 == code +14 +15 main: +16 # ecx <- start of video memory +17 8b/-> *0x7f28 1/r32/ecx +18 +19 # eax <- final pixel of video memory +20 8d/copy-address *(ecx + 0x0bffff) 0/r32/eax # 0xbffff = 1024*768 - 1 +21 +22 # for each pixel in video memory +23 { +24 39/compare %eax 1/r32/ecx +25 7c/jump-if-< break/disp8 +26 # write its column number to it +27 88/byte<- *eax 0/r32/AL +28 48/decrement-eax +29 eb/jump loop/disp8 +30 } +31 +32 # hang indefinitely +33 { +34 eb/jump loop/disp8 +35 } diff --git a/html/baremetal/ex3.mu.html b/html/baremetal/ex3.mu.html index 7d79c8c5..288b015a 100644 --- a/html/baremetal/ex3.mu.html +++ b/html/baremetal/ex3.mu.html @@ -73,10 +73,10 @@ if ('onhashchange' in window) { 15 var x/ecx: int <- copy 0 16 var y/edx: int <- copy 0 17 { -18 var key/eax: byte <- read-key 0 # real keyboard +18 var key/eax: byte <- read-key 0 # real keyboard 19 compare key, 0 20 loop-if-= # busy wait -21 pixel 0, x, y, 0x31 # green +21 pixel 0, x, y, 0x31 # green 22 x <- increment 23 compare x, 0x400 24 { diff --git a/html/baremetal/ex4.mu.html b/html/baremetal/ex4.mu.html index 30d0063d..c74e8633 100644 --- a/html/baremetal/ex4.mu.html +++ b/html/baremetal/ex4.mu.html @@ -69,7 +69,7 @@ if ('onhashchange' in window) { 11 12 fn main { 13 var g/eax: grapheme <- copy 0x41 # 'A' -14 draw-grapheme 0, g, 0x10, 0x10, 0xa +14 draw-grapheme 0, g, 0x10, 0x10, 0xa 15 } diff --git a/html/baremetal/ex6.mu.html b/html/baremetal/ex6.mu.html index 5121d218..01fd7ee4 100644 --- a/html/baremetal/ex6.mu.html +++ b/html/baremetal/ex6.mu.html @@ -78,15 +78,15 @@ if ('onhashchange' in window) { 20 x, y <- draw-text-wrapping-right-then-down 0, "Mu!", 0x10, 0x20, 0x78, 0x50, x, y, 0xa 21 22 # drawing at the cursor in multiple directions -23 x, y <- draw-text-wrapping-down-then-right-from-cursor-over-full-screen 0, "abc", 0xa -24 x, y <- draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0, "def", 0xa +23 draw-text-wrapping-down-then-right-from-cursor-over-full-screen 0, "abc", 0xa +24 draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0, "def", 0xa 25 26 # test drawing near the edge 27 x <- draw-text-rightward 0, "R", 0x3f8, 0x400, 0x100, 0xa -28 x, y <- draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0, "wrapped from R", 0xa +28 draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0, "wrapped from R", 0xa 29 -30 x <- draw-text-downward 0, "D", 0x100, 0x2f0, 0x300, 0xa -31 x, y <- draw-text-wrapping-down-then-right-from-cursor-over-full-screen 0, "wrapped from D", 0xa +30 x <- draw-text-downward 0, "D", 0x100, 0x2f0, 0x300, 0xa +31 draw-text-wrapping-down-then-right-from-cursor-over-full-screen 0, "wrapped from D", 0xa 32 } diff --git a/html/baremetal/ex7.mu.html b/html/baremetal/ex7.mu.html index f45d38dc..843225d1 100644 --- a/html/baremetal/ex7.mu.html +++ b/html/baremetal/ex7.mu.html @@ -69,7 +69,7 @@ if ('onhashchange' in window) { 11 # k, l. 12 13 fn main { -14 var key/eax: byte <- read-key 0 +14 var key/eax: byte <- read-key 0 15 { 16 compare key, 0x68 # 'h' 17 break-if-!= diff --git a/html/baremetal/mu-init.subx.html b/html/baremetal/mu-init.subx.html index 59895590..b765f7e0 100644 --- a/html/baremetal/mu-init.subx.html +++ b/html/baremetal/mu-init.subx.html @@ -63,12 +63,22 @@ if ('onhashchange' in window) { 9 # initialize stack 10 bd/copy-to-ebp 0/imm32 11 # no heap yet -12 (main) -13 -14 # hang indefinitely -15 { -16 eb/jump loop/disp8 -17 } +12 # +13 # always first run tests +14 (run-tests) +15 (num-test-failures) # => eax +16 # call main if tests all passed +17 { +18 3d/compare-eax-and 0/imm32 +19 75/jump-if-!= break/disp8 +20 (clear-screen) +21 (main) +22 } +23 +24 # hang indefinitely +25 { +26 eb/jump loop/disp8 +27 } -- cgit 1.4.1-2-gfad0