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 35  # 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 23  # jump to epilogue if != [label]
252   # read keycode into al
253   e4 60  # al <- port 0x60
254   # if (al & 0x80) a key is being lifted; return
255   50  # push eax
256   24 80  # al <- and 0x80
257   3c 00  # compare al, 0
258   58  # pop to eax (without touching flags)
259   75 19  # jump to epilogue if != [label]
260 # 13c:
261   # al <- *(keyboard normal map + eax)
262   8a  # copy m8 at rm32 to r8
263     80  # 10/mod/*+disp32 000/r8/al 000/rm32/eax
264     00 80 00 00  # disp32 [label]
265   # store al in keyboard buffer
266   88  # copy r8 to m8 at r32
267     81  # 10/mod/*+disp32 000/r8/al 001/rm32/ecx
268     d0 7d 00 00  # disp32 [label]
269 # 148:
270   # increment index
271   fe  # increment byte
272     05  # 00/mod/indirect 000/subop/increment 101/rm32/use-disp32
273     ce 7d 00 00  # disp32 [label]
274   # clear top nibble of index (keyboard buffer is circular)
275   80  # and byte
276     25  # 00/mod/indirect 100/subop/and 101/rm32/use-disp32
277     ce 7d 00 00  # disp32 [label]
278     0f  # imm8
279 # 155:
280   # epilogue
281   61  # pop all registers
282   fb  # enable interrupts
283   cf  # iret
284 
285 # padding
286 # 158:
287                         00 00 00 00 00 00 00 00
288 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
289 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
290 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
291 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
292 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
293 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
294 00 00 00 00 00 00 00 00 00 00 00 00 00 00
295 
296 # 1ce:
297 # var keyboard circular buffer
298 # write index: nibble
299   00
300 # 1cf:
301 # read index: nibble
302   00
303 # circular buffer: byte[16]
304   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
305 
306 # padding
307 # 1e0:
308 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
309 00 00 00 00 00 00 00 00
310 
311 # 1f8:
312 # idt_descriptor:
313   ff 00  # idt_end - idt_start - 1
314   00 7e 00 00  # start = idt_start [label]
315 
316 # 1fe:
317 # final 2 bytes of boot sector
318 55 aa
319 
320 ## sector 2
321 # loaded by load_disk, not automatically on boot
322 
323 # offset 200 (address 0x7e00): interrupt descriptor table
324 # 32 entries * 8 bytes each = 256 bytes (0x100)
325 # idt_start:
326 
327 00 00 00 00 00 00 00 00
328 00 00 00 00 00 00 00 00
329 00 00 00 00 00 00 00 00
330 00 00 00 00 00 00 00 00
331 00 00 00 00 00 00 00 00
332 00 00 00 00 00 00 00 00
333 00 00 00 00 00 00 00 00
334 00 00 00 00 00 00 00 00
335 
336 # entry 8: clock
337   00 7d  # target[0:16] = null 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 # entry 9: keyboard
344   10 7d  # target[0:16] = keyboard interrupt handler [label]
345   08 00  # segment selector (gdt_code)
346   00  # unused
347   8e  # 1/p 00/dpl 0 1110/type/32-bit-interrupt-gate
348   00 00  # target[16:32]
349 
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 00 00 00 00 00 00 00 00
366 00 00 00 00 00 00 00 00
367 00 00 00 00 00 00 00 00
368 00 00 00 00 00 00 00 00
369 00 00 00 00 00 00 00 00
370 00 00 00 00 00 00 00 00
371 00 00 00 00 00 00 00 00
372 # idt_end:
373 
374 # offset 300 (address 0x7f00):
375 # video mode info:
376   00 00  # attributes
377   00  # winA
378   00  # winB
379 # 304
380   00 00  # granularity
381   00 00  # winsize
382 # 308
383   00 00  # segmentA
384   00 00  # segmentB
385 # 30c
386   00 00 00 00  # realFctPtr (who knows)
387 # 310
388   00 00  # pitch
389   00 00  # Xres
390 # 314
391   00 00  # Yres
392   00 00  # Wchar Ychar
393 # 318
394   00  # planes
395   00  # bpp
396   00  # banks
397   00  # memory_model
398 # 31c
399   00  # bank_size
400   00  # image_pages
401   00  # reserved
402 # 31f
403   00 00  # red_mask red_position
404   00 00  # green_mask green_position
405   00 00  # blue_mask blue_position
406   00 00  # rsv_mask rsv_position
407   00  # directcolor_attributes
408 # 328
409   00 00 00 00  # physbase <== linear frame buffer
410 
411 # 32c
412 # reserved for video mode info
413                                     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 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
421 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
422 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
423 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
424 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
425 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
426 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
427 
428 # offset 400 (address 0x8000):
429 # keyboard normal map:
430 00
431 #  es
432    1b
433 #     |<--- digits -------------->| -  =  bs
434       31 32 33 34 35 36 37 38 39 30 2d 3d 08
435 # offset 40f
436 #  tb q  w  e  r  t  y  u  i  o  p  [  ]
437    09 71 77 65 72 74 79 75 69 6f 70 5b 5d
438 # offset 41c
439 #                                         enter
440                                           0a 00
441 # offset 41e
442 #     a  s  d  f  g  h  j  k  l  ;  '  `     \
443       61 73 64 66 67 68 6a 6b 6c 3b 27 60 00 5c
444 # offset 42c
445 #     z  x  c  v  b  n  m  ,  .  /
446       7a 78 63 76 62 6e 6d 2c 2e 2f
447 # offset 436
448                   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 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
455 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
456 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
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 
462 # 500:
463 # keyboard shift map:
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 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
474 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
475 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
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 
481 # 600:
482 # keyboard ctrl map:
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 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
493 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
494 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
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 
500 # padding (there might be more keyboard tables)
501 # 700:
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 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
512 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
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 
519 # 800:
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 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
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 # a00:
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 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
579 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
580 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
581 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
582 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
583 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
584 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
585 # offset c00 (address 0x8800)
586 
587 # vim:ft=subx