1 # Primitives for keyboard control. 2 # Require Linux and a modern terminal. 3 4 == code 5 6 enable-keyboard-immediate-mode: 7 # . prologue 8 55/push-ebp 9 89/<- %ebp 4/r32/esp 10 # . save registers 11 50/push-eax 12 51/push-ecx 13 52/push-edx 14 53/push-ebx 15 56/push-esi 16 57/push-edi 17 # 18 (_maybe-open-terminal) 19 # var terminal-info/esi: (addr termios) 20 # termios is a type from the Linux kernel. We don't care how large it is. 21 81 5/subop/subtract %esp 0x100/imm32 22 89/<- %esi 4/r32/esp 23 # ioctl(*Terminal-file-descriptor, TCGETS, terminal-info) 24 89/<- %edx 6/r32/esi 25 b9/copy-to-ecx 0x5401/imm32/TCGETS 26 8b/-> *Terminal-file-descriptor 3/r32/ebx 27 e8/call syscall_ioctl/disp32 28 # terminal-info->c_iflags &= Keyboard-immediate-mode-iflags 29 #? (write-buffered Stderr "iflags before: ") 30 #? (write-int32-hex-buffered Stderr *esi) 31 #? (write-buffered Stderr Newline) 32 #? (flush Stderr) 33 8b/-> *esi 0/r32/eax # Termios-c_iflag 34 23/and *Keyboard-immediate-mode-iflags 0/r32/eax 35 89/<- *esi 0/r32/eax # Termios-c_iflag 36 #? (write-buffered Stderr "iflags after: ") 37 #? (write-int32-hex-buffered Stderr *esi) 38 #? (write-buffered Stderr Newline) 39 #? (flush Stderr) 40 # terminal-info->c_lflags &= Keyboard-immediate-mode-lflags 41 #? (write-buffered Stderr "lflags before: ") 42 #? (write-int32-hex-buffered Stderr *(esi+0xc)) 43 #? (write-buffered Stderr Newline) 44 #? (flush Stderr) 45 8b/-> *(esi+0xc) 0/r32/eax # Termios-c_lflag 46 23/and *Keyboard-immediate-mode-lflags 0/r32/eax 47 89/<- *(esi+0xc) 0/r32/eax # Termios-c_lflag 48 #? (write-buffered Stderr "lflags after: ") 49 #? (write-int32-hex-buffered Stderr *(esi+0xc)) 50 #? (write-buffered Stderr Newline) 51 #? (flush Stderr) 52 # ioctl(*Terminal-file-descriptor, TCSETS, terminal-info) 53 89/<- %edx 6/r32/esi 54 b9/copy-to-ecx 0x5402/imm32/TCSETS 55 8b/-> *Terminal-file-descriptor 3/r32/ebx 56 e8/call syscall_ioctl/disp32 57 $enable-keyboard-immediate-mode:end: 58 # . reclaim locals 59 81 0/subop/add %esp 0x100/imm32 60 # . restore registers 61 5f/pop-to-edi 62 5e/pop-to-esi 63 5b/pop-to-ebx 64 5a/pop-to-edx 65 59/pop-to-ecx 66 58/pop-to-eax 67 # . epilogue 68 89/<- %esp 5/r32/ebp 69 5d/pop-to-ebp 70 c3/return 71 72 enable-keyboard-type-mode: 73 # . prologue 74 55/push-ebp 75 89/<- %ebp 4/r32/esp 76 # . save registers 77 50/push-eax 78 51/push-ecx 79 52/push-edx 80 53/push-ebx 81 56/push-esi 82 57/push-edi 83 # 84 (_maybe-open-terminal) 85 # var terminal-info/esi: (addr termios) 86 # termios is a type from the Linux kernel. We don't care how large it is. 87 81 5/subop/subtract %esp 0x100/imm32 88 89/<- %esi 4/r32/esp 89 # ioctl(*Terminal-file-descriptor, TCGETS, terminal-info) 90 89/<- %edx 6/r32/esi 91 b9/copy-to-ecx 0x5401/imm32/TCGETS 92 8b/-> *Terminal-file-descriptor 3/r32/ebx 93 e8/call syscall_ioctl/disp32 94 # terminal-info->c_iflags |= Keyboard-type-mode-iflags 95 8b/-> *esi 0/r32/eax # Termios-c_iflag 96 0b/or *Keyboard-type-mode-iflags 0/r32/eax 97 89/<- *esi 0/r32/eax # Termios-c_iflag 98 # terminal-info->c_lflags |= Keyboard-type-mode-lflags 99 8b/-> *(esi+0xc) 0/r32/eax # Termios-c_lflag 100 0b/or *Keyboard-type-mode-lflags 0/r32/eax 101 89/<- *(esi+0xc) 0/r32/eax # Termios-c_lflag 102 # ioctl(*Terminal-file-descriptor, TCSETS, terminal-info) 103 89/<- %edx 6/r32/esi 104 b9/copy-to-ecx 0x5402/imm32/TCSETS 105 8b/-> *Terminal-file-descriptor 3/r32/ebx 106 e8/call syscall_ioctl/disp32 107 $enable-keyboard-type-mode:end: 108 # . reclaim locals 109 81 0/subop/add %esp 0x100/imm32 110 # . restore registers 111 5f/pop-to-edi 112 5e/pop-to-esi 113 5b/pop-to-ebx 114 5a/pop-to-edx 115 59/pop-to-ecx 116 58/pop-to-eax 117 # . epilogue 118 89/<- %esp 5/r32/ebp 119 5d/pop-to-ebp 120 c3/return 121 122 read-key: # -> eax: byte 123 # . prologue 124 55/push-ebp 125 89/<- %ebp 4/r32/esp 126 # . save registers 127 51/push-ecx 128 # var buf/ecx: (stream byte 1) 129 68/push 0/imm32/data 130 68/push 1/imm32/size # 3 bytes of data unused 131 68/push 0/imm32/read 132 68/push 0/imm32/write 133 89/<- %ecx 4/r32/esp 134 # 135 (read 2 %ecx) # => eax 136 8b/-> *(ecx+0xc) 0/r32/eax 137 $read-key:end: 138 # . reclaim locals 139 81 0/subop/add %esp 0x10/imm32 140 # . restore registers 141 59/pop-to-ecx 142 # . epilogue 143 89/<- %esp 5/r32/ebp 144 5d/pop-to-ebp 145 c3/return 146 147 == data 148 149 # iflags: octal hex 150 # IGNBRK 0000001 0x0001 151 # BRKINT 0000002 0x0002 152 # IGNPAR 0000004 0x0004 153 # PARMRK 0000010 0x0008 154 # INPCK 0000020 0x0010 155 # ISTRIP 0000040 0x0020 156 # INLCR 0000100 0x0040 157 # IGNCR 0000200 0x0080 158 # ICRNL 0000400 0x0100 159 # IUCLC 0001000 0x0200 160 # IXON 0002000 0x0400 161 # IXANY 0004000 0x0800 162 # IXOFF 0010000 0x1000 163 # IMAXBEL 0020000 0x2000 164 # IUTF8 0040000 0x4000 165 166 # lflags: 167 # ISIG 0000001 0x0001 168 # ICANON 0000002 0x0002 169 # ECHO 0000010 0x0008 170 # ECHOE 0000020 0x0010 171 # ECHOK 0000040 0x0020 172 # ECHONL 0000100 0x0040 173 # NOFLSH 0000200 0x0080 174 # TOSTOP 0000400 0x0100 175 # IEXTEN 0100000 0x8000 176 177 # recipe for raw mode according to the termios.3 manpage on Linux: 178 # termios_p->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); 179 # termios_p->c_oflag &= ~OPOST; 180 # termios_p->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); 181 # termios_p->c_cflag &= ~(CSIZE | PARENB); 182 # termios_p->c_cflag |= CS8; 183 184 Keyboard-immediate-mode-iflags: # (addr tcflag_t) 185 #? 0xfffffa14 # ~IGNBRK & ~BRKINT & ~PARMRK & ~ISTRIP & ~INLCR & ~IGNCR & ~ICRNL & ~IXON 186 0xffffffff/imm32 187 188 Keyboard-immediate-mode-lflags: # (addr tcflag_t) 189 #? 0xffff7fb4/imm32 # ~ICANON & ~ISIG & ~IEXTEN & ~ECHO & ~ECHONL 190 0xffffffb5/imm32 # ~ICANON & ~ECHO & ~ECHONL 191 192 Keyboard-type-mode-iflags: # (addr tcflag_t) 193 0x00000000/imm32 # ~Keyboard-immediate-mode-iflags 194 195 Keyboard-type-mode-lflags: # (addr tcflag_t) 196 0x0000004a/imm32 # ~Keyboard-immediate-mode-lflags