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