https://github.com/akkartik/mu/blob/master/baremetal/ex3.hex
 1 # Draw pixels in response to keyboard events.
 2 #
 3 # To run, first prepare a realistically sized disk image:
 4 #   dd if=/dev/zero of=disk.img count=20160  # 512-byte sectors, so 10MB
 5 # Load the program on the disk image:
 6 #   cat baremetal/boot.hex baremetal/ex3.hex  |./bootstrap run apps/hex  > a.bin
 7 #   dd if=a.bin of=disk.img conv=notrunc
 8 # To run:
 9 #   qemu-system-i386 disk.img
10 # Or:
11 #   bochs -f baremetal/boot.bochsrc  # boot.bochsrc loads disk.img
12 
13 # main:  (address 0x8800)
14 
15 # eax <- LFB
16 8b  # copy *rm32 to r32
17   05  # 00/mod/indirect 000/r32/eax 101/rm32/use-disp32
18   28 7f 00 00 # disp32 [label]
19 
20 # var read index/ecx: byte = 0
21 31 c9  # ecx <- xor ecx;  11/direct 001/r32/ecx 001/rm32/ecx
22 
23 # $loop:
24   # CL = *read index
25   8a  # copy m8 at r32 to r8
26     0d  # 00/mod/indirect 001/r8/cl 101/rm32/use-disp32
27     cf 7d 00 00  # disp32 [label]
28   # CL = *(keyboard buffer + ecx)
29   8a  # copy m8 at r32 to r8
30     89  # 10/mod/*+disp32 001/r8/cl 001/rm32/ecx
31     d0 7d 00 00  # disp32 [label]
32   # if (CL == 0) loop (spin loop)
33   80
34     f9  # 11/mod/direct 111/subop/compare 001/rm8/CL
35     00  # imm8
36   74 ef  # loop -17 [label]
37 # offset 0x19:
38   # otherwise increment read index
39   fe  # increment byte
40     05  # 00/mod/indirect 000/subop/increment 101/rm32/use-disp32
41     cf 7d 00 00  # disp32 [label]
42   # clear top nibble of index (keyboard buffer is circular)
43   80  # and byte
44     25  # 00/mod/indirect 100/subop/and 101/rm32/use-disp32
45     cf 7d 00 00  # disp32 [label]
46     0f  # imm8
47   # print a pixel in fluorescent green
48   c6  # copy imm8 to m8 at rm32
49     00  # 00/mod/indirect 000/subop 000/rm32/eax
50     31  # imm32
51   40  # increment eax
52   eb dc # loop -36 [label]
53 
54 # $break:
55 e9 fb ff ff ff  # hang indefinitely
56 
57 # vim:ft=subx