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