https://github.com/akkartik/mu/blob/main/baremetal/103grapheme.subx
  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