https://github.com/akkartik/mu/blob/main/baremetal/boot.hex
  1 # Code for the first 2 disk sectors, that all programs in this directory need:
  2 #   - load sectors past the first (using BIOS primitives) since only the first is available by default
  3 #     - if this fails, print 'D' at top-left of screen and halt
  4 #   - initialize a minimal graphics mode
  5 #   - switch to 32-bit mode (giving up access to BIOS primitives)
  6 #   - set up a handler for keyboard events
  7 #   - jump to start of program
  8 #
  9 # To convert to a disk image, first prepare a realistically sized disk image:
 10 #   dd if=/dev/zero of=disk.img count=20160  # 512-byte sectors, so 10MB
 11 # Create initial sectors from this file:
 12 #   ./bootstrap run apps/hex < baremetal/boot.hex > boot.bin
 13 # Translate other sectors into a file called a.img
 14 # Load all sectors into the disk image:
 15 #   cat boot.bin a.img > disk.bin
 16 #   dd if=disk.bin of=disk.img conv=notrunc
 17 # To run:
 18 #   qemu-system-i386 disk.img
 19 # Or:
 20 #   bochs -f baremetal/boot.bochsrc  # boot.bochsrc loads disk.img
 21 #
 22 # Since we start out in 16-bit mode, we need instructions SubX doesn't
 23 # support.
 24 # This file contains just lowercase hex bytes and comments. Zero
 25 # error-checking. Make liberal use of:
 26 #   - comments documenting expected offsets
 27 #   - size checks on the emitted file (currently: 512 bytes)
 28 #   - xxd to eyeball that offsets contain expected bytes
 29 #
 30 # Programs using this initialization:
 31 #   - can't use any syscalls
 32 #   - can't print text to video memory (past these boot sectors)
 33 #   - must only print raw pixels (256 colors) to video memory (resolution 1024x768)
 34 #   - must store their entry-point at address 0x8800
 35 
 36 ## 16-bit entry point
 37 
 38 # Upon reset, the IBM PC:
 39 #   - loads the first sector (512 bytes)
 40 #     from some bootable image (see the boot sector marker at the end of this file)
 41 #     to the address range [0x7c00, 0x7e00)
 42 #   - starts executing code at address 0x7c00
 43 
 44 # offset 00 (address 0x7c00):
 45   # disable interrupts for this initialization
 46   fa  # cli
 47 
 48   # initialize segment registers
 49   # this isn't always needed, but the recommendation is to not make assumptions
 50   b8 00 00  # ax <- 0
 51   8e d8  # ds <- ax
 52   8e d0  # ss <- ax
 53   8e c0  # es <- ax
 54   8e e0  # fs <- ax
 55   8e e8  # gs <- ax
 56 
 57   # We don't read or write the stack before we get to 32-bit mode. No function
 58   # calls, so we don't need to initialize the stack.
 59 
 60 # 0e:
 61   # load second sector from disk
 62   b4 02  # ah <- 2  # read sectors from disk
 63   # dl comes conveniently initialized at boot time with the index of the device being booted
 64   b5 00  # ch <- 0  # cylinder 0
 65   b6 00  # dh <- 0  # track 0
 66   b1 02  # cl <- 2  # second sector, 1-based
 67   b0 10  # al <- 16  # number of sectors to read; all sectors must be in a single track
 68   # address to write sectors to = es:bx = 0x7e00, contiguous with boot segment
 69   bb 00 00  # bx <- 0
 70   8e c3  # es <- bx
 71   bb 00 7e  # bx <- 0x7e00 [label]
 72   cd 13  # int 13h, BIOS disk service
 73   0f 82 8a 00  # jump-if-carry disk-error [label]
 74 
 75 # 26:
 76   # undo the A20 hack: https://en.wikipedia.org/wiki/A20_line
 77   # this is from https://github.com/mit-pdos/xv6-public/blob/master/bootasm.S
 78   # seta20.1:
 79   e4 64  # al <- port 0x64
 80   a8 02  # set zf if bit 1 (second-least significant) is not set
 81   75 fa  # if zf not set, goto seta20.1 (-6)
 82 
 83   b0 d1  # al <- 0xd1
 84   e6 64  # port 0x64 <- al
 85 
 86 # 30:
 87   # seta20.2:
 88   e4 64  # al <- port 0x64
 89   a8 02  # set zf if bit 1 (second-least significant) is not set
 90   75 fa  # if zf not set, goto seta20.2 (-6)
 91 
 92   b0 df  # al <- 0xdf
 93   e6 64  # port 0x64 <- al
 94 
 95 # 3a:
 96   # adjust video mode
 97   b4 4f  # ah <- 4f (VBE)
 98   b0 02  # al <- 02 (set video mode)
 99   bb 05 41  # bx <- 0x0105 (graphics 1024x768x256
100             #               0x4000 bit = configure linear frame buffer in Bochs emulator; hopefully this doesn't hurt anything when running natively)
101             # fallback mode: 0x0101 (640x480x256)
102   cd 10  # int 10h, Vesa BIOS extensions
103 
104 # 43:
105   # load information for the (hopefully) current video mode
106   # mostly just for the address to the linear frame buffer
107   b4 4f  # ah <- 4f (VBE)
108   b0 01  # al <- 01 (get video mode)
109   b9 07 01  # cx <- 0x0107 (mode we requested)
110   bf 00 7f  # di <- 0x7f00 (video mode info) [label]
111   cd 10
112 
113 # 4f:
114   # switch to 32-bit mode
115   0f 01 16  # lgdt 00/mod/indirect 010/subop 110/rm/use-disp16
116     a0 7c  # *gdt_descriptor [label]
117   0f 20 c0  # eax <- cr0
118   66 83 c8 01  # eax <- or 0x1
119   0f 22 c0  # cr0 <- eax
120   ea e0 7c 08 00  # far jump to initialize_32bit_mode after setting cs to the record at offset 8 in the gdt (gdt_code) [label]
121 
122 # padding
123 # 63:
124          00 00 00 00 00 00 00 00 00 00 00 00 00
125 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
126 
127 ## GDT: 3 records of 8 bytes each
128 
129 # 80:
130 # gdt_start:
131 # gdt_null:  mandatory null descriptor
132   00 00 00 00 00 00 00 00
133 # gdt_code:  (offset 8 from gdt_start)
134   ff ff  # limit[0:16]
135   00 00 00  # base[0:24]
136   9a  # 1/present 00/privilege 1/descriptor type = 1001b
137       # 1/code 0/conforming 1/readable 0/accessed = 1010b
138   cf  # 1/granularity 1/32-bit 0/64-bit-segment 0/AVL = 1100b
139       # limit[16:20] = 1111b
140   00  # base[24:32]
141 # gdt_data:  (offset 16 from gdt_start)
142   ff ff  # limit[0:16]
143   00 00 00  # base[0:24]
144   92  # 1/present 00/privilege 1/descriptor type = 1001b
145       # 0/data 0/conforming 1/readable 0/accessed = 0010b
146   cf  # same as gdt_code
147   00  # base[24:32]
148 # gdt_end:
149 
150 # padding
151 # 98:
152                         00 00 00 00 00 00 00 00
153 
154 # a0:
155 # gdt_descriptor:
156   17 00  # final index of gdt = gdt_end - gdt_start - 1
157   80 7c 00 00  # start = gdt_start [label]
158 
159 # padding
160 # a5:
161                   00 00 00 00 00 00 00 00 00 00
162 
163 # b0:
164 # disk_error:
165   # print 'D' to top-left of screen to indicate disk error
166   # *0xb8000 <- 0x0f44
167   # bx <- 0xb800
168   bb 00 b8
169   # ds <- bx
170   8e db  # 11b/mod 011b/reg/ds 011b/rm/bx
171   # al <- 'D'
172   b0 44
173   # ah <- 0x0f  # white on black
174   b4 0f
175   # bx <- 0
176   bb 00 00
177   # *ds:bx <- ax
178   89 07  # 00b/mod/indirect 000b/reg/ax 111b/rm/bx
179 
180 e9 fb ff  # loop forever
181 
182 # padding
183 # c1:
184    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
185 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
186 
187 ## 32-bit code from this point (still some instructions not in SubX)
188 
189 # e0:
190 # initialize_32bit_mode:
191   66 b8 10 00  # ax <- offset 16 from gdt_start
192   8e d8  # ds <- ax
193   8e d0  # ss <- ax
194   8e c0  # es <- ax
195   8e e0  # fs <- ax
196   8e e8  # gs <- ax
197 
198   # load interrupt handlers
199   0f 01 1d  # lidt 00/mod/indirect 011/subop 101/rm32/use-disp32
200     f8 7d 00 00  # *idt_descriptor [label]
201 
202   # enable keyboard IRQ
203   b0 fd  # al <- 0xfd  # enable just IRQ1
204   e6 21  # port 0x21 <- al
205 
206   # initialization is done; enable interrupts
207   fb
208   e9 01 0b 00 00  # jump to 0x8800 [label]
209 
210 # padding
211 # ff:
212                                              00
213 
214 # 100:
215 # null interrupt handler:
216   cf  # iret
217 
218 # padding
219 # 101:
220    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
221 
222 # 110:
223 # keyboard interrupt handler:
224   # prologue
225   fa  # disable interrupts
226   60  # push all registers to stack
227   # acknowledge interrupt
228   b0 20  # al <- 0x20
229   e6 20  # port 0x20 <- al
230   # read status into eax
231   31 c0  # eax <- xor eax;  11/direct 000/r32/eax 000/rm32/eax
232   e4 64  # al <- port 0x64
233   # if (status & 0x1) == 0, return
234   24 01  # al <- and 0x1
235   3c 00  # compare al, 0
236   74 2d  # jump to epilogue if = [label]
237 # 120:
238   # if keyboard buffer is full, return
239   31 c9  # ecx <- xor ecx;  11/direct 001/r32/ecx 001/rm32/ecx
240   # . var index/ecx: byte
241   8a  # copy m8 at r32 to r8
242     0d  # 00/mod/indirect 001/r8/cl 101/rm32/use-disp32
243     ce 7d 00 00  # disp32 [label]
244   # . al = *(keyboard buffer + index)
245   8a  # copy m8 at r32 to r8
246     81  # 10/mod/*+disp32 000/r8/al 001/rm32/ecx
247     d0 7d 00 00  # disp32 [label]
248   # . if (al != 0) return
249   3c 00  # compare al, 0
250 # 130:
251   75 1b  # jump to epilogue if != [label]
252   # read keycode into al
253   e4 60  # al <- port 0x60
254   # al <- *(keyboard normal map + eax)
255   8a  # copy m8 at rm32 to r8
256     80  # 10/mod/*+disp32 000/r8/al 000/rm32/eax
257     00 80 00 00  # disp32 [label]
258   # store al in keyboard buffer
259   88  # copy r8 to m8 at r32
260     81  # 10/mod/*+disp32 000/r8/al 001/rm32/ecx
261     d0 7d 00 00  # disp32 [label]
262 # 140:
263   # increment index
264   fe  # increment byte
265     05  # 00/mod/indirect 000/subop/increment 101/rm32/use-disp32
266     ce 7d 00 00  # disp32 [label]
267   # clear top nibble of index (keyboard buffer is circular)
268   80  # and byte
269     25  # 00/mod/indirect 100/subop/and 101/rm32/use-disp32
270     ce 7d 00 00  # disp32 [label]
271     0f  # imm8
272 # 14d:
273   # epilogue
274   61  # pop all registers
275   fb  # enable interrupts
276   cf  # iret
277 
278 # padding
279 # 150:
280 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
281 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
282 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
283 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
284 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
285 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
286 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
287 00 00 00 00 00 00 00 00 00 00 00 00 00 00
288 
289 # 1ce:
290 # var keyboard circular buffer
291 # write index: nibble
292 00
293 # 1cf:
294 # read index: nibble
295 00
296 # circular buffer: byte[16]
297 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
298 
299 # padding
300 # 1e0:
301 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
302 00 00 00 00 00 00 00 00
303 
304 # 1f8:
305 # idt_descriptor:
306   ff 00  # idt_end - idt_start - 1
307   00 7e 00 00  # start = idt_start [label]
308 
309 # 1fe:
310 # final 2 bytes of boot sector
311 55 aa
312 
313 ## sector 2
314 # loaded by load_disk, not automatically on boot
315 
316 # offset 200 (address 0x7e00): interrupt descriptor table
317 # 32 entries * 8 bytes each = 256 bytes (0x100)
318 # idt_start:
319 
320 00 00 00 00 00 00 00 00
321 00 00 00 00 00 00 00 00
322 00 00 00 00 00 00 00 00
323 00 00 00 00 00 00 00 00
324 00 00 00 00 00 00 00 00
325 00 00 00 00 00 00 00 00
326 00 00 00 00 00 00 00 00
327 00 00 00 00 00 00 00 00
328 
329 # entry 8: clock
330   00 7d  # target[0:16] = null interrupt handler [label]
331   08 00  # segment selector (gdt_code)
332   00  # unused
333   8e  # 1/p 00/dpl 0 1110/type/32-bit-interrupt-gate
334   00 00  # target[16:32]
335 
336 # entry 9: keyboard
337   10 7d  # target[0:16] = keyboard interrupt handler [label]
338   08 00  # segment selector (gdt_code)
339   00  # unused
340   8e  # 1/p 00/dpl 0 1110/type/32-bit-interrupt-gate
341   00 00  # target[16:32]
342 
343 00 00 00 00 00 00 00 00
344 00 00 00 00 00 00 00 00
345 00 00 00 00 00 00 00 00
346 00 00 00 00 00 00 00 00
347 00 00 00 00 00 00 00 00
348 00 00 00 00 00 00 00 00
349 00 00 00 00 00 00 00 00
350 00 00 00 00 00 00 00 00
351 00 00 00 00 00 00 00 00
352 00 00 00 00 00 00 00 00
353 00 00 00 00 00 00 00 00
354 00 00 00 00 00 00 00 00
355 00 00 00 00 00 00 00 00
356 00 00 00 00 00 00 00 00
357 00 00 00 00 00 00 00 00
358 00 00 00 00 00 00 00 00
359 00 00 00 00 00 00 00 00
360 00 00 00 00 00 00 00 00
361 00 00 00 00 00 00 00 00
362 00 00 00 00 00 00 00 00
363 00 00 00 00 00 00 00 00
364 00 00 00 00 00 00 00 00
365 # idt_end:
366 
367 # offset 300 (address 0x7f00):
368 # video mode info:
369   00 00  # attributes
370   00  # winA
371   00  # winB
372 # 304
373   00 00  # granularity
374   00 00  # winsize
375 # 308
376   00 00  # segmentA
377   00 00  # segmentB
378 # 30c
379   00 00 00 00  # realFctPtr (who knows)
380 # 310
381   00 00  # pitch
382   00 00  # Xres
383 # 314
384   00 00  # Yres
385   00 00  # Wchar Ychar
386 # 318
387   00  # planes
388   00  # bpp
389   00  # banks
390   00  # memory_model
391 # 31c
392   00  # bank_size
393   00  # image_pages
394   00  # reserved
395 # 31f
396   00 00  # red_mask red_position
397   00 00  # green_mask green_position
398   00 00  # blue_mask blue_position
399   00 00  # rsv_mask rsv_position
400   00  # directcolor_attributes
401 # 328
402   00 00 00 00  # physbase <== linear frame buffer
403 
404 # 32c
405 # reserved for video mode info
406                                     00 00 00 00
407 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
408 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
409 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
411 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
412 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
413 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
414 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
415 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
416 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
417 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
418 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
419 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
420 
421 # offset 400 (address 0x8000):
422 # keyboard normal map:
423 00
424 #  es
425    1b
426 #     |<--- digits -------------->| -  =  bs
427       31 32 33 34 35 36 37 38 39 30 2d 3d 08
428 # offset 40f
429 #  tb q  w  e  r  t  y  u  i  o  p  [  ]
430    09 71 77 65 72 74 79 75 69 6f 70 5b 5d
431 # offset 41c
432 #                                         enter
433                                           0a 00
434 # offset 41e
435 #     a  s  d  f  g  h  j  k  l  ;  '  `     \
436       61 73 64 66 67 68 6a 6b 6c 3b 27 60 00 5c
437 # offset 42c
438 #     z  x  c  v  b  n  m  ,  .  /
439       7a 78 63 76 62 6e 6d 2c 2e 2f
440 # offset 436
441                   00 00 00 00 00 00 00 00 00 00
442 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
443 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
444 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
445 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
446 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
447 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
448 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
449 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
451 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
452 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
453 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
454 
455 # 500:
456 # keyboard shift map:
457 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
458 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
459 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
460 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
461 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
462 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
463 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
464 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
465 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
466 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
467 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
468 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
469 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
470 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
471 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
472 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
473 
474 # 600:
475 # keyboard ctrl map:
476 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
477 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
478 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
479 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
480 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
481 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
482 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
483 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
484 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
485 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
486 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
487 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
488 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
489 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
491 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
492 
493 # padding (there might be more keyboard tables)
494 # 700:
495 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
496 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
497 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
498 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
499 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
500 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
501 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
502 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
503 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
504 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
505 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
506 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
507 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
508 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
509 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
510 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
511 
512 # 800:
513 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
514 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
515 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
516 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
517 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
518 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
519 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
520 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
521 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
522 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
523 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
524 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
525 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
526 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
527 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
528 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
529 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
530 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
531 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
532 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
533 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
534 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
535 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
536 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
537 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
538 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
539 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
540 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
541 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
542 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
543 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
544 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
545 # a00:
546 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
547 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
548 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
549 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
550 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
551 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
552 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
553 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
554 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
555 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
556 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
557 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
558 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
559 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
560 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
561 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
562 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
563 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
564 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
565 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
566 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
567 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
568 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
569 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
570 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
571 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
572 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
573 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
574 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
575 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
576 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
577 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
578 # offset c00 (address 0x8800)
579 
580 # vim:ft=subx