diff options
Diffstat (limited to 'boot.hex')
-rw-r--r-- | boot.hex | 1181 |
1 files changed, 1181 insertions, 0 deletions
diff --git a/boot.hex b/boot.hex new file mode 100644 index 00000000..6fa874c2 --- /dev/null +++ b/boot.hex @@ -0,0 +1,1181 @@ +# Code for the first few disk sectors that all programs in this directory need: +# - load sectors past the first (using BIOS primitives) since only the first is available by default +# - if this fails, print 'D' at top-left of screen and halt +# - initialize a minimal graphics mode +# - switch to 32-bit mode (giving up access to BIOS primitives) +# - set up a handler for keyboard events +# - jump to start of program +# +# To convert to a disk image, first prepare a realistically sized disk image: +# dd if=/dev/zero of=disk.img count=20160 # 512-byte sectors, so 10MB +# Create initial sectors from this file: +# ./bootstrap run apps/hex < baremetal/boot.hex > boot.bin +# Translate other sectors into a file called a.img +# Load all sectors into the disk image: +# cat boot.bin a.img > disk.bin +# dd if=disk.bin of=disk.img conv=notrunc +# To run: +# qemu-system-i386 disk.img +# Or: +# bochs -f baremetal/boot.bochsrc # boot.bochsrc loads disk.img +# +# Since we start out in 16-bit mode, we need instructions SubX doesn't +# support. +# This file contains just lowercase hex bytes and comments. Programming it +# requires liberal use of: +# - comments documenting expected offsets +# - size checks on the emitted file (currently: 6144 bytes) +# - xxd to spot-check contents of specific offsets in the generated output +# +# Programs using this initialization: +# - can't use any syscalls +# - can't print text to video memory (past these boot sectors) +# - must only print raw pixels (256 colors) to video memory (resolution 1024x768) +# - must start executing immediately after this file (see outline below) +# +# Don't panic! This file doesn't contain any loops or function calls. 80% of +# it is data. One pass through less than 1KB of code (there's lots of +# padding), and then we jump into a better notation. The rest of the stack +# (really only in a couple of slightly higher-level places) needs to know just +# a few magic constants: +# Video memory: start is stored at 0x8128 +# Keyboard buffer: starts at 0x8028 +# +# No mouse support. _That_ would require panicking. + +# Outline of this file with offsets and the addresses they map to at run-time: +# -- 16-bit mode code +# offset 0 (address 7c00): boot code +# -- 16-bit mode data +# e0 (address 7c80) global descriptor table +# f8 (address 7ca0) <== gdt_descriptor +# -- 32-bit mode code +# offset 100 (address 7d00): boot code +# 1fe (address 7dfe) boot sector marker (2 bytes) +# offset 200 (address 7e00): interrupt handler code +# -- 32-bit mode data +# offset 400 (address 8000): handler data +# 410 (address 8010): keyboard handler data +# 428 (address 8028) <== keyboard buffer +# offset 500 (address 8100): video mode data (256 bytes) +# 528 (address 8128) <== start of video RAM stored here +# offset 600 (address 8200): interrupt descriptor table (1KB) +# offset a00 (address 8600): keyboard mappings (1.5KB) +# offset 1000 (address 8c00): bitmap font (2KB) +# offset 1800 (address 9400): entrypoint for applications (don't forget to adjust survey_baremetal if this changes) + +# Other details of the current memory map: +# code: 4 tracks of disk to [0x00007c00, 0x00027400) +# stack grows down from 0x00070000 +# see below +# heap: [0x01000000, 0x02000000) +# see baremetal/120allocate.subx +# Consult https://wiki.osdev.org/Memory_Map_(x86) before modifying any of this. + +## 16-bit entry point + +# Upon reset, the IBM PC: +# - loads the first sector (512 bytes) +# from some bootable image (see the boot sector marker at the end of this file) +# to the address range [0x7c00, 0x7e00) +# - starts executing code at address 0x7c00 + +# offset 00 (address 0x7c00): + # disable interrupts for this initialization + fa # cli + + # initialize segment registers + # this isn't always needed, but the recommendation is to not make assumptions + b8 00 00 # ax <- 0 + 8e d8 # ds <- ax + 8e c0 # es <- ax + 8e e0 # fs <- ax + 8e e8 # gs <- ax + + # initialize stack to 0x00070000 + # We don't read or write the stack before we get to 32-bit mode, but BIOS + # calls do. We need to move the stack in case BIOS initializes it to some + # low address that we want to write code into. + b8 00 70 # ax <- 0x7000 + 8e d0 # ss <- ax + bc 00 00 # sp <- 0x0000 + + # undo the A20 hack: https://en.wikipedia.org/wiki/A20_line + # this is from https://github.com/mit-pdos/xv6-public/blob/master/bootasm.S + # seta20.1: + e4 64 # al <- port 0x64 + a8 02 # set zf if bit 1 (second-least significant) is not set + 75 fa # if zf not set, goto seta20.1 (-6) + b0 d1 # al <- 0xd1 + e6 64 # port 0x64 <- al + # seta20.2: + e4 64 # al <- port 0x64 + a8 02 # set zf if bit 1 (second-least significant) is not set + 75 fa # if zf not set, goto seta20.2 (-6) + b0 df # al <- 0xdf + e6 64 # port 0x64 <- al + + # load remaining sectors from first two tracks of disk into addresses [0x7e00, 0x17800) + b4 02 # ah <- 2 # read sectors from disk + # dl comes conveniently initialized at boot time with the index of the device being booted + b5 00 # ch <- 0 # cylinder 0 + b6 00 # dh <- 0 # track 0 + b1 02 # cl <- 2 # second sector, 1-based + b0 7d # al <- 125 # number of sectors to read = 2*63 - 1 + # address to write sectors to = es:bx = 0x7e00, contiguous with boot segment + bb 00 00 # bx <- 0 + 8e c3 # es <- bx + bb 00 7e # bx <- 0x7e00 [label] + cd 13 # int 13h, BIOS disk service + 0f 82 a3 00 # jump-if-carry disk_error [label] + + # load two more tracks of disk into addresses [0x17800, 0x27400) + b4 02 # ah <- 2 # read sectors from disk + # dl comes conveniently initialized at boot time with the index of the device being booted + b5 00 # ch <- 0 # cylinder 0 + b6 02 # dh <- 2 # track 0 + b1 01 # cl <- 1 # first sector, 1-based + b0 7e # al <- 126 # number of sectors to read = 2*63 + # address to write sectors to = es:bx = 0x17800 + bb 80 17 # bx <- 0x1780 [label] + 8e c3 # es <- bx + bb 00 00 # bx <- 0 + cd 13 # int 13h, BIOS disk service + 0f 82 9b 00 # jump-if-carry disk_error [label] + + # load two more tracks of disk into addresses [0x27400, 0x37000) + b4 02 # ah <- 2 # read sectors from disk + # dl comes conveniently initialized at boot time with the index of the device being booted + b5 00 # ch <- 0 # cylinder 0 + b6 02 # dh <- 2 # track 0 + b1 01 # cl <- 1 # first sector, 1-based + b0 7e # al <- 126 # number of sectors to read = 2*63 + # address to write sectors to = es:bx = 0x17800 + bb 80 17 # bx <- 0x1780 [label] + 8e c3 # es <- bx + bb 00 00 # bx <- 0 + cd 13 # int 13h, BIOS disk service + 0f 82 9b 00 # jump-if-carry disk_error [label] + + # reset es + bb 00 00 # bx <- 0 + 8e c3 # es <- bx + + # adjust video mode + b4 4f # ah <- 4f (VBE) + b0 02 # al <- 02 (set video mode) + bb 05 41 # bx <- 0x0105 (graphics 1024x768x256 + # 0x4000 bit = configure linear frame buffer in Bochs emulator; hopefully this doesn't hurt anything when running natively) + # fallback mode: 0x0101 (640x480x256) + cd 10 # int 10h, Vesa BIOS extensions + + # load information for the (hopefully) current video mode + # mostly just for the address to the linear frame buffer + b4 4f # ah <- 4f (VBE) + b0 01 # al <- 01 (get video mode info) + b9 07 01 # cx <- 0x0107 (mode we requested) + bf 00 81 # di <- 0x8100 (video mode info) [label] + cd 10 + + # switch to 32-bit mode + 0f 01 16 # lgdt 00/mod/indirect 010/subop 110/rm/use-disp16 + f8 7c # *gdt_descriptor [label] + 0f 20 c0 # eax <- cr0 + 66 83 c8 01 # eax <- or 0x1 + 0f 22 c0 # cr0 <- eax + ea 00 7d 08 00 # far jump to initialize_32bit_mode after setting cs to the record at offset 8 in the gdt (gdt_code) [label] + +# padding +# 8e: + 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +# cf: +# disk_error: + # print 'D' to top-left of screen to indicate disk error + # *0xb8000 <- 0x0f44 + # bx <- 0xb800 + bb 00 b8 + # ds <- bx + 8e db # 11b/mod 011b/reg/ds 011b/rm/bx + # al <- 'D' + b0 44 + # ah <- 0x0f # white on black + b4 0f + # bx <- 0 + bb 00 00 + # *ds:bx <- ax + 89 07 # 00b/mod/indirect 000b/reg/ax 111b/rm/bx + +e9 fd ff # loop forever + +## GDT: 3 records of 8 bytes each + +# e0: +# gdt_start: +# gdt_null: mandatory null descriptor + 00 00 00 00 00 00 00 00 +# gdt_code: (offset 8 from gdt_start) + ff ff # limit[0:16] + 00 00 00 # base[0:24] + 9a # 1/present 00/privilege 1/descriptor type = 1001b + # 1/code 0/conforming 1/readable 0/accessed = 1010b + cf # 1/granularity 1/32-bit 0/64-bit-segment 0/AVL = 1100b + # limit[16:20] = 1111b + 00 # base[24:32] +# gdt_data: (offset 16 from gdt_start) + ff ff # limit[0:16] + 00 00 00 # base[0:24] + 92 # 1/present 00/privilege 1/descriptor type = 1001b + # 0/data 0/conforming 1/readable 0/accessed = 0010b + cf # same as gdt_code + 00 # base[24:32] +# gdt_end: + +# f8: +# gdt_descriptor: + 17 00 # final index of gdt = gdt_end - gdt_start - 1 + e0 7c 00 00 # start = gdt_start [label] + +# padding +# fe: + 00 00 + +## 32-bit code from this point (still some instructions not in SubX) + +# offset 100 (address 0x7d00): +# initialize_32bit_mode: + 66 b8 10 00 # ax <- offset 16 from gdt_start + 8e d8 # ds <- ax + 8e d0 # ss <- ax + 8e c0 # es <- ax + 8e e0 # fs <- ax + 8e e8 # gs <- ax + +# 10e: + bc 00 00 07 00 # esp <- 0x00070000 + +# 113: + # load interrupt handlers + 0f 01 1d # lidt 00/mod/indirect 011/subop 101/rm32/use-disp32 + 00 80 00 00 # *idt_descriptor [label] + + # For now, not bothering reprogramming the IRQ to not conflict with software + # exceptions. + # https://wiki.osdev.org/index.php?title=8259_PIC&oldid=24650#Protected_Mode + # + # Interrupt 1 (keyboard) conflicts with debugger faults. We don't use a + # debugger. + # Reference: + # https://wiki.osdev.org/Exceptions + +# 11a: + # enable keyboard IRQ (1) + b0 fd # al <- 0xfd # disable mask for IRQ1 + e6 21 # port 0x21 <- al + +# 11e: + fb # enable interrupts + db e3 # initialize FPU + # eax <- cr4 + 0f 20 # copy cr4 to rm32 + e0 # 11/mod/direct 100/r32/CR4 000/rm32/eax + # eax <- or bit 9 + 0f ba + e8 # 11/mod/direct 101/subop/bit-test-and-set 000/rm32/eax + 09 # imm8 + # cr4 <- eax + 0f 22 # copy rm32 to cr4 + e0 # 11/mod/direct 100/r32/CR4 000/rm32/eax + e9 d0 16 00 00 # jump to 0x9400 [label] + +# padding +# 130: +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +# 1fe: +# final 2 bytes of boot sector +55 aa + +## sector 2 onwards loaded by load_disk, not automatically on boot + +# offset 200 (address 0x7e00): +# null interrupt handler: + cf # iret + +# padding +# 201: + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +# 210: +# keyboard interrupt handler: + # prologue + fa # disable interrupts + 60 # push all registers to stack + # acknowledge interrupt + b0 20 # al <- 0x20 + e6 20 # port 0x20 <- al + 31 c0 # eax <- xor eax; 11/direct 000/r32/eax 000/rm32/eax + # check output buffer of 8042 keyboard controller (https://web.archive.org/web/20040604041507/http://panda.cs.ndsu.nodak.edu/~achapwes/PICmicro/keyboard/atkeyboard.html) + e4 64 # al <- port 0x64 + a8 01 # set zf if bit 0 (least significant) is not set + 74 bb # jump to epilogue if 0 bit is not set [label] +# 21e: + # - if keyboard buffer is full, return + 31 c9 # ecx <- xor ecx; 11/direct 001/r32/ecx 001/rm32/ecx + # var index/ecx: byte + 8a # copy m8 at r32 to r8 + 0d # 00/mod/indirect 001/r8/cl 101/rm32/use-disp32 + 28 80 00 00 # disp32 [label] + # al = *(keyboard buffer + index) + 8a # copy m8 at r32 to r8 + 81 # 10/mod/*+disp32 000/r8/al 001/rm32/ecx + 30 80 00 00 # disp32 [label] + # if (al != 0) return + 3c 00 # compare al, 0 + 75 a9 # jump to epilogue if != [label] +# 230: + # - read keycode + e4 60 # al <- port 0x60 + # - key released + # if (al == 0xaa) shift = false # left shift is being lifted + 3c aa # compare al, 0xaa + 75 0a # jump to $1 if != [label] + # *shift = 0 + c7 # copy imm32 to rm32 + 05 # 00/mod/indirect 000/subop/copy 101/rm32/use-disp32 + 10 80 00 00 # disp32 [label] + 00 00 00 00 # imm32 +# 240: +# $1: + # if (al == 0xb6) shift = false # right shift is being lifted + 3c b6 # compare al, 0xb6 + 75 0a # jump to $2 if != [label] + # *shift = 0 + c7 # copy imm32 to rm32 + 05 # 00/mod/indirect 000/subop/copy 101/rm32/use-disp32 + 10 80 00 00 # disp32 [label] + 00 00 00 00 # imm32 +# 24e: +# $2: + # if (al == 0x9d) ctrl = false # ctrl is being lifted + 3c 9d # compare al, 0x9d + 75 0a # jump to $3 if != [label] + # *ctrl = 0 + c7 # copy imm32 to rm32 + 05 # 00/mod/indirect 000/subop/copy 101/rm32/use-disp32 + 14 80 00 00 # disp32 [label] + 00 00 00 00 # imm32 +# 25c: +# $3: + # if (al & 0x80) a key is being lifted; return + 50 # push eax + 24 80 # al <- and 0x80 + 3c 00 # compare al, 0 + 58 # pop to eax (without touching flags) + 75 75 # jump to epilogue if != [label] +# 264: + # - key pressed + # if (al == 0x2a) shift = true, return # left shift pressed + 3c 2a # compare al, 0x2a + 75 0c # jump to $4 if != [label] + # *shift = 1 + c7 # copy imm32 to rm32 + 05 # 00/mod/indirect 000/subop/copy 101/rm32/use-disp32 + 10 80 00 00 # disp32 [label] + 01 00 00 00 # imm32 + eb 65 # jump to epilogue [label] +# 274: +# $4: + # if (al == 0x36) shift = true, return # right shift pressed + 3c 36 # compare al, 0x36 + 75 0c # jump to $5 if != [label] + # *shift = 1 + c7 # copy imm32 to rm32 + 05 # 00/mod/indirect 000/subop/copy 101/rm32/use-disp32 + 10 80 00 00 # disp32 [label] + 01 00 00 00 # imm32 + eb 55 # jump to epilogue [label] +# 284: +# $5: + # if (al == 0x1d) ctrl = true, return + 3c 1d # compare al, 0x36 + 75 0c # jump to $6 if != [label] + # *shift = 1 + c7 # copy imm32 to rm32 + 05 # 00/mod/indirect 000/subop/copy 101/rm32/use-disp32 + 14 80 00 00 # disp32 [label] + 01 00 00 00 # imm32 + eb 45 # jump to epilogue [label] +# 294: +# $6: + # - convert key to character + # if (shift) use keyboard shift map + 81 # operate on rm32 and imm32 + 3d # 00/mod/indirect 111/subop/compare 101/rm32/use-disp32 + 10 80 00 00 # disp32 = shift [label] + 00 00 00 00 # imm32 + 74 08 # jump to $7 if = [label] + # al <- *(keyboard shift map + eax) + 8a # copy m8 at rm32 to r8 + 80 # 10/mod/*+disp32 000/r8/al 000/rm32/eax + 00 87 00 00 # disp32 [label] + eb 1a # jump to $8 [label] +# 2a8: +# $7: + # if (ctrl) use keyboard ctrl map + 81 # operate on rm32 and imm32 + 3d # 00/mod/indirect 111/subop/compare 101/rm32/use-disp32 + 14 80 00 00 # disp32 = ctrl [label] + 00 00 00 00 # imm32 + 74 08 # jump to $8 if = [label] + # al <- *(keyboard ctrl map + eax) + 8a # copy m8 at rm32 to r8 + 80 # 10/mod/*+disp32 000/r8/al 000/rm32/eax + 00 88 00 00 # disp32 [label] + eb 06 # jump to $9 [label] +# 2bc: +# $8: + # otherwise use keyboard normal map + # al <- *(keyboard normal map + eax) + 8a # copy m8 at rm32 to r8 + 80 # 10/mod/*+disp32 000/r8/al 000/rm32/eax + 00 86 00 00 # disp32 [label] +# 2c2: +# $9: + # - if there's no character mapping, return + 3c 00 # compare al, 0 + 74 13 # jump to epilogue if = [label] +# 2c6: + # - store al in keyboard buffer + 88 # copy r8 to m8 at r32 + 81 # 10/mod/*+disp32 000/r8/al 001/rm32/ecx + 30 80 00 00 # disp32 [label] + # increment index + fe # increment byte + 05 # 00/mod/indirect 000/subop/increment 101/rm32/use-disp32 + 28 80 00 00 # disp32 [label] + # clear top nibble of index (keyboard buffer is circular) + 80 # and byte + 25 # 00/mod/indirect 100/subop/and 101/rm32/use-disp32 + 28 80 00 00 # disp32 [label] + 0f # imm8 +# 2d9: + # epilogue + 61 # pop all registers + fb # enable interrupts + cf # iret + +# padding +# 2dc: + 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +# 300: +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +# offset 400 (address 0x8000): interrupt handler data +# idt_descriptor: + ff 03 # idt_end - idt_start - 1 + 00 82 00 00 # start = idt_start [label] + +# padding +# 406: + 00 00 00 00 00 00 00 00 00 00 + +# 410: +# var shift: boolean + 00 00 00 00 + +# 414: +# var ctrl: boolean + 00 00 00 00 + +# padding +# 418: + 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 + +# 428: +# var keyboard circular buffer +# write index: nibble +# still take up 4 bytes so SubX can handle it + 00 00 00 00 +# 42c: +# read index: nibble +# still take up 4 bytes so SubX can handle it + 00 00 00 00 +# 430: +# circular buffer: byte[16] + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +# padding +# 440: +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +# offset 500 (address 0x8100): +# video mode info {{{ + 00 00 # attributes + 00 # winA + 00 # winB +# 04 + 00 00 # granularity + 00 00 # winsize +# 08 + 00 00 # segmentA + 00 00 # segmentB +# 0c + 00 00 00 00 # realFctPtr (who knows) +# 10 + 00 00 # pitch + 00 00 # Xres +# 14 + 00 00 # Yres + 00 00 # Wchar Ychar +# 18 + 00 # planes + 00 # bpp + 00 # banks + 00 # memory_model +# 1c + 00 # bank_size + 00 # image_pages + 00 # reserved +# 1f + 00 00 # red_mask red_position + 00 00 # green_mask green_position + 00 00 # blue_mask blue_position + 00 00 # rsv_mask rsv_position + 00 # directcolor_attributes +# 28 + 00 00 00 00 # physbase <== linear frame buffer + +# 2c +# reserved for video mode info + 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +# }}} + +# offset 600 (address 0x8200): +# interrupt descriptor table {{{ +# 128 entries * 8 bytes each = 1024 bytes (0x400) +# idt_start: + +# entry 0 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 + +# By default, BIOS maps IRQ0-7 to interrupt vectors 8-15. +# https://wiki.osdev.org/index.php?title=Interrupts&oldid=25102#Default_PC_Interrupt_Vector_Assignment + +# entry 8: clock + 00 7e # target[0:16] = null interrupt handler [label] + 08 00 # segment selector (gdt_code) + 00 # unused + 8e # 1/p 00/dpl 0 1110/type/32-bit-interrupt-gate + 00 00 # target[16:32] + +# entry 9: keyboard + 10 7e # target[0:16] = keyboard interrupt handler [label] + 08 00 # segment selector (gdt_code) + 00 # unused + 8e # 1/p 00/dpl 0 1110/type/32-bit-interrupt-gate + 00 00 # target[16:32] + +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 + +# 500: +# entry 0x20 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 + +# 600: +# entry 0x40 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 + +# 700: +# entry 0x60 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +# entry 0x70 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +# idt_end: +# }}} + +## the rest of this file has data + +# offset a00 (address 0x8600): +# translating keys to ASCII {{{ +# keyboard normal map: +00 +# es + 1b +# |<--- digits -------------->| - = backspace + 31 32 33 34 35 36 37 38 39 30 2d 3d 08 +# 0f +# tab q w e r t y u i o p [ ] + 09 71 77 65 72 74 79 75 69 6f 70 5b 5d +# 1c +# enter (newline) + 0a 00 +# 1e +# a s d f g h j k l ; ' ` \ + 61 73 64 66 67 68 6a 6b 6c 3b 27 60 00 5c + # ^ left shift +# 2c +# z x c v b n m , . / * + 7a 78 63 76 62 6e 6d 2c 2e 2f 00 2a + # ^ right shift +# 38 +# space + 00 20 +# 3a + 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +# numeric keypad would start here, but isn't implemented + 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +# offset b00: +# keyboard shift map: +00 +# es + 1b +# ! @ # $ % ^ & * ( ) _ + backspace + 21 40 23 24 25 53 26 2a 28 29 5f 2b 08 +# 0f +# tab Q W E R T Y U I O P { } + 09 51 57 45 52 54 59 55 49 5f 50 7b 7d +# 1c +# enter (newline) + 0a 00 +# 1e +# A S D F G H J K L : " ~ | + 41 53 44 46 47 48 4a 4b 4c 3a 22 7e 00 7c +# 2c +# Z X C V B N M < > ? * + 5a 58 43 56 42 4e 4d 3c 3e 3f 00 2a +# 38 +# space + 00 20 +# 3a + 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +# numeric keypad would start here, but isn't implemented + 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +# c00: +# keyboard ctrl map: +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +# 10 +# ^q ^w ^e ^r ^t ^y ^u tb ^o ^p + 11 17 05 12 14 19 15 09 1f 10 00 00 +# 1c +# carriage-return + 0d 00 +# 1e +# ^a ^s ^d ^f ^g ^h ^j ^j ^l ^\ + 01 13 04 06 07 08 0a 0b 0c 00 00 00 00 1c +# 2c +# ^z ^x ^c ^v ^b ^n ^m ^/ + 1a 18 03 16 02 0e 0d 00 00 1f 00 00 +# 38 + 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +# padding (there might be more keyboard tables) +# d00: +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +# e00: +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +# f00: +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +# }}} + +# offset 1000 (address 0x8c00) +# Bitmaps for some ASCII characters (soon Unicode) {{{ +# Part of GNU Unifont +# 8px wide, 16px tall +# Based on http://unifoundry.com/pub/unifont/unifont-13.0.05/font-builds/unifont-13.0.05.hex.gz +# See https://en.wikipedia.org/wiki/GNU_Unifont#The_.hex_font_format +# Website: http://unifoundry.com/unifont/index.html +# License: http://unifoundry.com/LICENSE.txt (GPL v2) +# Each line below is a bitmap for a single character. +# Each byte is a bitmap for a single row of 8 pixels. + +# some unprintable ASCII chars + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +# 0x20 = space + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +# ! + 00 00 00 00 08 08 08 08 08 08 08 00 08 08 00 00 +# " + 00 00 22 22 22 22 00 00 00 00 00 00 00 00 00 00 +# 0x23 = '#' + 00 00 00 00 12 12 12 7e 24 24 7e 48 48 48 00 00 +# $ + 00 00 00 00 08 3e 49 48 38 0e 09 49 3e 08 00 00 +# % + 00 00 00 00 31 4a 4a 34 08 08 16 29 29 46 00 00 +# & + 00 00 00 00 1c 22 22 14 18 29 45 42 46 39 00 00 +# ' + 00 00 08 08 08 08 00 00 00 00 00 00 00 00 00 00 +# ( + 00 00 00 04 08 08 10 10 10 10 10 10 08 08 04 00 +# ) + 00 00 00 20 10 10 08 08 08 08 08 08 10 10 20 00 +# * + 00 00 00 00 00 00 08 49 2a 1c 2a 49 08 00 00 00 +# + + 00 00 00 00 00 00 08 08 08 7f 08 08 08 00 00 00 +# , + 00 00 00 00 00 00 00 00 00 00 00 00 18 08 08 10 +# - + 00 00 00 00 00 00 00 00 00 3c 00 00 00 00 00 00 +# . + 00 00 00 00 00 00 00 00 00 00 00 00 18 18 00 00 +# / + 00 00 00 00 02 02 04 08 08 10 10 20 40 40 00 00 +# 0x30 = '0' + 00 00 00 00 18 24 42 46 4a 52 62 42 24 18 00 00 +# 1 + 00 00 00 00 08 18 28 08 08 08 08 08 08 3e 00 00 +# 2 + 00 00 00 00 3c 42 42 02 0c 10 20 40 40 7e 00 00 +# 3 + 00 00 00 00 3c 42 42 02 1c 02 02 42 42 3c 00 00 +# 4 + 00 00 00 00 04 0c 14 24 44 44 7e 04 04 04 00 00 +# 5 + 00 00 00 00 7e 40 40 40 7c 02 02 02 42 3c 00 00 +# 6 + 00 00 00 00 1c 20 40 40 7c 42 42 42 42 3c 00 00 +# 7 + 00 00 00 00 7e 02 02 04 04 04 08 08 08 08 00 00 +# 8 + 00 00 00 00 3c 42 42 42 3c 42 42 42 42 3c 00 00 +# 9 + 00 00 00 00 3c 42 42 42 3e 02 02 02 04 38 00 00 +# : + 00 00 00 00 00 00 18 18 00 00 00 18 18 00 00 00 +# ; + 00 00 00 00 00 00 18 18 00 00 00 18 08 08 10 00 +# < + 00 00 00 00 00 02 04 08 10 20 10 08 04 02 00 00 +# = + 00 00 00 00 00 00 00 7e 00 00 00 7e 00 00 00 00 +# > + 00 00 00 00 00 40 20 10 08 04 08 10 20 40 00 00 +# ? + 00 00 00 00 3c 42 42 02 04 08 08 00 08 08 00 00 +# 0x40 = @ + 00 00 00 00 1c 22 4a 56 52 52 52 4e 20 1e 00 00 +# A + 00 00 00 00 18 24 24 42 42 7e 42 42 42 42 00 00 +# B + 00 00 00 00 7c 42 42 42 7c 42 42 42 42 7c 00 00 +# C + 00 00 00 00 3c 42 42 40 40 40 40 42 42 3c 00 00 +# D + 00 00 00 00 78 44 42 42 42 42 42 42 44 78 00 00 +# E + 00 00 00 00 7e 40 40 40 7c 40 40 40 40 7e 00 00 +# F + 00 00 00 00 7e 40 40 40 7c 40 40 40 40 40 00 00 +# G + 00 00 00 00 3c 42 42 40 40 4e 42 42 46 3a 00 00 +# H + 00 00 00 00 42 42 42 42 7e 42 42 42 42 42 00 00 +# I + 00 00 00 00 3e 08 08 08 08 08 08 08 08 3e 00 00 +# J + 00 00 00 00 1f 04 04 04 04 04 04 44 44 38 00 00 +# K + 00 00 00 00 42 44 48 50 60 60 50 48 44 42 00 00 +# L + 00 00 00 00 40 40 40 40 40 40 40 40 40 7e 00 00 +# M + 00 00 00 00 42 42 66 66 5a 5a 42 42 42 42 00 00 +# N + 00 00 00 00 42 62 62 52 52 4a 4a 46 46 42 00 00 +# O + 00 00 00 00 3c 42 42 42 42 42 42 42 42 3c 00 00 +# 0x50 = P + 00 00 00 00 7c 42 42 42 7c 40 40 40 40 40 00 00 +# Q + 00 00 00 00 3c 42 42 42 42 42 42 5a 66 3c 03 00 +# R + 00 00 00 00 7c 42 42 42 7c 48 44 44 42 42 00 00 +# S + 00 00 00 00 3c 42 42 40 30 0c 02 42 42 3c 00 00 +# T + 00 00 00 00 7f 08 08 08 08 08 08 08 08 08 00 00 +# U + 00 00 00 00 42 42 42 42 42 42 42 42 42 3c 00 00 +# V + 00 00 00 00 41 41 41 22 22 22 14 14 08 08 00 00 +# W + 00 00 00 00 42 42 42 42 5a 5a 66 66 42 42 00 00 +# X + 00 00 00 00 42 42 24 24 18 18 24 24 42 42 00 00 +# Y + 00 00 00 00 41 41 22 22 14 08 08 08 08 08 00 00 +# Z + 00 00 00 00 7e 02 02 04 08 10 20 40 40 7e 00 00 +# [ + 00 00 00 0e 08 08 08 08 08 08 08 08 08 08 0e 00 +# \ + 00 00 00 00 40 40 20 10 10 08 08 04 02 02 00 00 +# ] + 00 00 00 70 10 10 10 10 10 10 10 10 10 10 70 00 +# ^ + 00 00 18 24 42 00 00 00 00 00 00 00 00 00 00 00 +# _ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 7f 00 +# 0x60 = backtick + 00 20 10 08 00 00 00 00 00 00 00 00 00 00 00 00 +# a + 00 00 00 00 00 00 3c 42 02 3e 42 42 46 3a 00 00 +# b + 00 00 00 40 40 40 5c 62 42 42 42 42 62 5c 00 00 +# c + 00 00 00 00 00 00 3c 42 40 40 40 40 42 3c 00 00 +# d + 00 00 00 02 02 02 3a 46 42 42 42 42 46 3a 00 00 +# e + 00 00 00 00 00 00 3c 42 42 7e 40 40 42 3c 00 00 +# f + 00 00 00 0c 10 10 10 7c 10 10 10 10 10 10 00 00 +# g + 00 00 00 00 00 02 3a 44 44 44 38 20 3c 42 42 3c +# h + 00 00 00 40 40 40 5c 62 42 42 42 42 42 42 00 00 +# i + 00 00 00 08 08 00 18 08 08 08 08 08 08 3e 00 00 +# j + 00 00 00 04 04 00 0c 04 04 04 04 04 04 04 48 30 +# k + 00 00 00 40 40 40 44 48 50 60 50 48 44 42 00 00 +# l + 00 00 00 18 08 08 08 08 08 08 08 08 08 3e 00 00 +# m + 00 00 00 00 00 00 76 49 49 49 49 49 49 49 00 00 +# n + 00 00 00 00 00 00 5c 62 42 42 42 42 42 42 00 00 +# o + 00 00 00 00 00 00 3c 42 42 42 42 42 42 3c 00 00 +# 0x70 = p + 00 00 00 00 00 00 5c 62 42 42 42 42 62 5c 40 40 +# q + 00 00 00 00 00 00 3a 46 42 42 42 42 46 3a 02 02 +# r + 00 00 00 00 00 00 5c 62 42 40 40 40 40 40 00 00 +# s + 00 00 00 00 00 00 3c 42 40 30 0c 02 42 3c 00 00 +# t + 00 00 00 00 10 10 10 7c 10 10 10 10 10 0c 00 00 +# u + 00 00 00 00 00 00 42 42 42 42 42 42 46 3a 00 00 +# v + 00 00 00 00 00 00 42 42 42 24 24 24 18 18 00 00 +# w + 00 00 00 00 00 00 41 49 49 49 49 49 49 36 00 00 +# x + 00 00 00 00 00 00 42 42 24 18 18 24 42 42 00 00 +# y + 00 00 00 00 00 00 42 42 42 42 42 26 1a 02 02 3c +# z + 00 00 00 00 00 00 7e 02 04 08 10 20 40 7e 00 00 +# { + 00 00 00 0c 10 10 08 08 10 20 10 08 08 10 10 0c +# | + 00 00 08 08 08 08 08 08 08 08 08 08 08 08 08 08 +# } + 00 00 00 30 08 08 10 10 08 04 08 10 10 08 08 30 +# ~ + 00 00 00 31 49 46 00 00 00 00 00 00 00 00 00 00 +# 0x7f = del (unused) + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +# }}} + +# offset 1800 (address 0x9400) + +# vim:ft=subx |