summary refs log tree commit diff stats
path: root/doc/print_keys.py
blob: f87a2a408ae3b609de5cc1e9b3ad113ba8a4b55f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/env python
"""
You can use this tool to find out values of keypresses
"""

from curses import *

sep = '; '

@wrapper
def main(w):
	while True:
		w.addstr(str(w.getch()) + sep)
0'>210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307
# Helper to print an int32 in decimal.

== code
#   instruction                     effective address                                                   register    displacement    immediate
# . op          subop               mod             rm32          base        index         scale       r32
# . 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

print-int32-decimal:  # out : (address stream), n : int32
    # works by generating characters from lowest to highest and pushing them
    # to the stack, before popping them one by one into the stream
    #
    # pseudocode:
    #   push sentinel
    #   EAX = abs(n)
    #   while true
    #     sign-extend EAX into EDX
    #     EAX, EDX = EAX/10, EAX%10
    #     EDX += '0'
    #     push EDX
    #     if (EAX == 0) break
    #   if n < 0
    #     push '-'
    #   w = out->write
    #   curr = &out->data[out->write]
    #   max = &out->data[out->length]
    #   while true
    #     pop into EAX
    #     if (EAX == sentinel) break
    #     if (curr >= max) abort
    #     *curr = AL
    #     ++curr
    #     ++w
    #   out->write = w
    # (based on K&R itoa: https://en.wikibooks.org/wiki/C_Programming/stdlib.h/itoa)
    # (this pseudocode contains registers because operations like division
    # require specific registers in x86)
    #
    # . prolog
    55/push-EBP
    89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
    # . save registers
    50/push-EAX
    51/push-ECX
    52/push-EDX
    53/push-EBX
    57/push-EDI
    # ten/ECX = 10
    b9/copy-to-ECX  0xa/imm32
    # push sentinel
    68/push  0/imm32/sentinel
    # EAX = abs(n)
    8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           0/r32/EAX   0xc/disp8       .                 # copy *(EBP+12) to EAX
    3d/compare-EAX-with  0/imm32
    7d/jump-if-greater-or-equal  $print-int32-decimal:read-loop/disp8
$print-int32-decimal:negative:
    f7          3/subop/negate      3/mod/direct    0/rm32/EAX    .           .             .           .           .               .                 # negate EAX
$print-int32-decimal:read-loop:
    # EAX, EDX = EAX / 10, EAX % 10
    99/sign-extend-EAX-into-EDX
    f7          7/subop/idiv        3/mod/direct    1/rm32/ECX    .           .             .           .           .               .                 # divide EDX:EAX by ECX, storing quotient in EAX and remainder in EDX
    # EDX += '0'
    81          0/subop/add         3/mod/direct    2/rm32/EDX    .           .             .           .           .               0x30/imm32        # add to EDX
    # push EDX
    52/push-EDX
    # if (EAX == 0) break
    3d/compare-EAX-and  0/imm32
    7f/jump-if-greater  $print-int32-decimal:read-loop/disp8
$print-int32-decimal:read-break:
    # if (n < 0) push('-')
    81          7/subop/compare     1/mod/*+disp8   5/rm32/EBP    .           .             .           .           0xc/disp8       0/imm32           # compare *(EBP+12)
    7d/jump-if-greater-or-equal  $print-int32-decimal:write/disp8
$print-int32-decimal:push-negative:
    68/push  0x2d/imm32/-
$print-int32-decimal:write:
    # EDI = out
    8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           7/r32/EDI   8/disp8         .                 # copy *(EBP+8) to EDI
    # w/EDX = out->write
    8b/copy                         0/mod/indirect  7/rm32/EDI    .           .             .           2/r32/EDX   .               .                 # copy *EDI to EDX
    # curr/ECX = &out->data[out->write]
    8d/copy-address                 1/mod/*+disp8   4/rm32/sib    7/base/EDI  2/index/EDX   .           1/r32/ECX   0xc/disp8       .                 # copy EBX+EDX+12 to ECX
    # max/EBX = &out->data[out->length]
    8b/copy                         1/mod/*+disp8   7/rm32/EDI    .           .             .           3/r32/EBX   8/disp8         .                 # copy *(EDI+8) to EBX
    8d/copy-address                 1/mod/*+disp8   4/rm32/sib    7/base/EDI  3/index/EBX   .           3/r32/EBX   0xc/disp8       .                 # copy EDI+EBX+12 to EBX
$print-int32-decimal:write-loop:
    # pop into EAX
    58/pop-to-EAX
    # if (EAX == sentinel) break
    3d/compare-EAX-and  0/imm32/sentinel
    74/jump-if-equal  $print-int32-decimal:write-break/disp8
    # if (curr >= max) abort
    39/compare                      3/mod/direct    1/rm32/ECX    .           .             .           3/r32/EBX   .               .                 # compare ECX with EBX
    73/jump-if-greater-or-equal-unsigned  $print-int32-decimal:abort/disp8
$print-int32-decimal:write-char:
    # *curr = AL
    88/copy-byte                    0/mod/indirect  1/rm32/ECX    .           .             .           0/r32/AL    .               .                 # copy AL to byte at *ECX
    # ++curr
    41/increment-ECX
    # ++w
    42/increment-EDX
    eb/jump  $print-int32-decimal:write-loop/disp8
$print-int32-decimal:write-break:
    # out->write = w
    89/copy                         0/mod/indirect  7/rm32/EDI    .           .             .           2/r32/EDX   .               .                 # copy EDX to *EDI
$print-int32-decimal:end:
    # . restore registers
    5f/pop-to-EDI
    5b/pop-to-EBX
    5a/pop-to-EDX
    59/pop-to-ECX
    58/pop-to-EAX
    # . epilog
    89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
    5d/pop-to-EBP
    c3/return

$print-int32-decimal:abort:
    # . _write(2/stderr, error)
    # . . push args
    68/push  "print-int32-decimal: out of space\n"/imm32
    68/push  2/imm32/stderr
    # . . call
    e8/call  _write/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
    # . syscall(exit, 1)
    bb/copy-to-EBX  1/imm32
    b8/copy-to-EAX  1/imm32/exit
    cd/syscall  0x80/imm8
    # never gets here

test-print-int32-decimal:
    # - check that a single-digit number converts correctly
    # setup
    # . clear-stream(_test-stream)
    # . . push args
    68/push  _test-stream/imm32
    # . . call
    e8/call  clear-stream/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
    # print-int32-decimal(_test-stream, 9)
    # . . push args
    68/push  9/imm32
    68/push  _test-stream/imm32
    # . . call
    e8/call  print-int32-decimal/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
    # check-stream-equal(_test-stream, "9", msg)
    # . . push args
    68/push  "F - test-print-int32-decimal"/imm32
    68/push  "9"/imm32
    68/push  _test-stream/imm32
    # . . call
    e8/call  check-stream-equal/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    # . end
    c3/return

test-print-int32-decimal-zero:
    # - check that 0 converts correctly
    # setup
    # . clear-stream(_test-stream)
    # . . push args
    68/push  _test-stream/imm32
    # . . call
    e8/call  clear-stream/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
    # print-int32-decimal(_test-stream, 0)
    # . . push args
    68/push  0/imm32
    68/push  _test-stream/imm32
    # . . call
    e8/call  print-int32-decimal/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
    # check-stream-equal(_test-stream, "0", msg)
    # . . push args
    68/push  "F - test-print-int32-decimal-zero"/imm32
    68/push  "0"/imm32
    68/push  _test-stream/imm32
    # . . call
    e8/call  check-stream-equal/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    # . end
    c3/return

test-print-int32-decimal-multiple-digits:
    # - check that a multi-digit number converts correctly
    # setup
    # . clear-stream(_test-stream)
    # . . push args
    68/push  _test-stream/imm32
    # . . call
    e8/call  clear-stream/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
    # print-int32-decimal(_test-stream, 10)
    # . . push args
    68/push  0xa/imm32
    68/push  _test-stream/imm32
    # . . call
    e8/call  print-int32-decimal/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
    # check-stream-equal(_test-stream, "10", msg)
    # . . push args
    68/push  "F - test-print-int32-decimal-multiple-digits"/imm32
    68/push  "10"/imm32
    68/push  _test-stream/imm32
    # . . call
    e8/call  check-stream-equal/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    # . end
    c3/return

test-print-int32-decimal-negative:
    # - check that a negative single-digit number converts correctly
    # setup
    # . clear-stream(_test-stream)
    # . . push args
    68/push  _test-stream/imm32
    # . . call
    e8/call  clear-stream/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
    # print-int32-decimal(_test-stream, -9)
    # . . push args
    68/push  -9/imm32
    68/push  _test-stream/imm32
    # . . call
    e8/call  print-int32-decimal/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
#?     # dump _test-stream {{{
#?     # . write(2/stderr, "^")
#?     # . . push args
#?     68/push  "^"/imm32
#?     68/push  2/imm32/stderr
#?     # . . call
#?     e8/call  write/disp32
#?     # . . discard args
#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
#?     # . write-stream(2/stderr, _test-stream)
#?     # . . push args
#?     68/push  _test-stream/imm32
#?     68/push  2/imm32/stderr
#?     # . . call
#?     e8/call  write-stream/disp32
#?     # . . discard args
#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
#?     # . write(2/stderr, "$\n")
#?     # . . push args
#?     68/push  "$\n"/imm32
#?     68/push  2/imm32/stderr
#?     # . . call
#?     e8/call  write/disp32
#?     # . . discard args
#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
#?     # }}}
    # check-stream-equal(_test-stream, "-9", msg)
    # . . push args
    68/push  "F - test-print-int32-decimal-negative"/imm32
    68/push  "-9"/imm32
    68/push  _test-stream/imm32
    # . . call
    e8/call  check-stream-equal/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    # . end
    c3/return

test-print-int32-decimal-negative-multiple-digits:
    # - check that a multi-digit number converts correctly
    # setup
    # . clear-stream(_test-stream)
    # . . push args
    68/push  _test-stream/imm32
    # . . call
    e8/call  clear-stream/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
    # print-int32-decimal(_test-stream, -10)
    # . . push args
    68/push  -0xa/imm32
    68/push  _test-stream/imm32
    # . . call
    e8/call  print-int32-decimal/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
    # check-stream-equal(_test-stream, "-10", msg)
    # . . push args
    68/push  "F - test-print-int32-decimal-negative-multiple-digits"/imm32
    68/push  "-10"/imm32
    68/push  _test-stream/imm32
    # . . call
    e8/call  check-stream-equal/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    # . end
    c3/return

# . . vim:nowrap:textwidth=0