https://github.com/akkartik/mu/blob/main/102keyboard.subx
 1 # check keyboard for a key
 2 # return 0 on no keypress or unrecognized key
 3 #
 4 # We need to do this in machine code because Mu doesn't have global variables
 5 # yet (for the keyboard buffer).
 6 
 7 == code
 8 
 9 # Most keys correspond to their ASCII/Unicode values.
10 # TODO: Support for international keyboards and multi-byte Unicode.
11 #
12 # However there are some exceptions that have no assigned place in Unicode
13 # (and with good reason):
14 #   0x80 = left arrow ←
15 #   0x81 = down arrow ↓
16 #   0x82 = up arrow ↑
17 #   0x83 = right arrow →
18 # These code points are not used by Unicode and their semantics are agreed to
19 # be context-sensitive: https://en.wikipedia.org/wiki/C0_and_C1_control_codes#C1_controls.
20 # Mu cannibalizes them in yet another non-standard way.
21 read-key:  # kbd: (addr keyboard) -> result/eax: byte
22     # . prologue
23     55/push-ebp
24     89/<- %ebp 4/r32/esp
25     # . save registers
26     51/push-ecx
27     # result = 0
28     b8/copy-to-eax 0/imm32
29     # ecx = keyboard
30     8b/-> *(ebp+8) 1/r32/ecx
31     81 7/subop/compare %ecx 0/imm32
32     {
33       75/jump-if-!= break/disp8
34       # var buffer-byte-addr/ecx: (addr byte)
35       8b/-> *Keyboard-buffer:read 1/r32/CL
36       81 0/subop/add %ecx Keyboard-buffer:data/imm32
37       # var next-key/eax: byte = *buffer-byte-addr
38       8a/byte-> *ecx 0/r32/AL
39       # if (next-key != 0) lock and remove from keyboard buffer
40       3d/compare-eax-with 0/imm32
41       {
42         74/jump-if-= break/disp8
43         fa/disable-interrupts
44         c6 0/subop/copy-byte *ecx 0/imm8
45         ff 0/subop/increment *Keyboard-buffer:read
46         81 4/subop/and *Keyboard-buffer:read 0x0f/imm32
47         fb/enable-interrupts
48       }
49       # return
50       eb $read-key:end/disp8
51     }
52     # TODO: fake keyboard
53 $read-key:end:
54     # . restore registers
55     59/pop-to-ecx
56     # . epilogue
57     89/<- %esp 5/r32/ebp
58     5d/pop-to-ebp
59     c3/return