about summary refs log blame commit diff stats
path: root/boot.subx
blob: 497a5ddbc01c88c79a6176f9c08c48a9b7bc30c9 (plain) (tree)
1
2
3
4
5
6
7
                                                                               





                                                                                                      




                                                                                                                                                

                                                                              






                                                      
                                                           

                                                      


                                                     



                                                                 

                                                                                                                     
 
                                          
                                                      
                                    
               
                                  
                          
                                                                               
 

       


                         
                                        
                                                                                       

                                             
 
                                              

                     
                                
                       



                                           
 



                                                                           
                            
                                           
                        
 

                                                                             














                                                                                         
                                                                                         
                                                
                                                                                            



                                                                       
                                                                              
                       
                                          
                            
                                         
                                       
 
                                                                  
                                                
                                                                                            


                                         


                                                                               
                                          
                       
                                         
                                       
 
                                                                  
                                                
                                                                                            





                                                                               
                                          
                       
                                         
                                       
 
            
                       
                                          
 
                     







                                                                                                                                                        

                                                           

                                             
                                                 
                                     

                                          




                                                                              
                                                                                       
                 
                                              


                                                                      
                              
       
                                              

                                                                                        
                                                                     
                                                                                 

       

         

                                               

                                               
                                               
 


           

                                                          
                            
                                          





                                                         
                      
   
 
                                 
       
 

                                                
                         
                    






                                                             
                     







                                                         
              


                                                    
 
                              
 



                                           
                                               
       




                                          
 
                                 
 
                           


                                                                              
                                                                                       
 









                                                                                

                                                  
 

                      
                                           

                                             
              
                                              
                   
                                                                        
              
                                              
       
                                          
       
 
                            



                                                                  
 
                       


            
      

                                               


                           





                                   
                                                              
                                                                                                                                                                           
                          
                                                         
                                                       
      
                                        
                                                              
                       

                                                       
                                 
                                   

                                                
                                 
                       
                        
                                         
      
                  
                          



                                                               


                                                            
                                 
                        
      


                                                                
                                   


                                                            
                                 
                        
      
     









                                                            




                                                

                                         


                                                              
                                   


                                                            
                                 
                        


                                  

                                                               
                                   


                                                            
                                 
                        













                                                            
                              
                                     

                                                               
                                         
                        
                                  


                                                
                                 















                                                               
                                     
                                      
                             
                                                
                                 

      
                                             

                                        
      
                                 

                                                
                                 


                                                                 
                                 


                                                           
                                 
              
      




                         
                                    
 



                                               








                                               
      





                                               














                                                 

                
                     


                     
    

                      
    

                   
    
                                       
    

                
    

                      
    



                    
    


                   
    




                                    
    

                                                 
    














                                               
     
 
              

                                                 
          
 
         








                       


                                                                                                      
                
                                              


                                                    
                                                                                   

                   
                                                  


                                                    
                                                                                       






















                       

      
            

































                       
            

































                       
            















                       
            















                       
          
     
 
              
                               
                    


     
                                                   
                                            
    
                                        
                                         
    
                                                         
                                               
    

                                               
                                                      
    

                                         
                                                 
    

                                
    
                                               

                                                        
 

                   




                                                   
    
                                        
                                         
    
                                                         
                                               
    

                                               
    

                                         
    

                                
    


                                                        
 

                  
                                               











                                                         

     

              












































































































































































































































                                                                                               
                              

             
# 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

# Code in this file needs to be more deliberate about the SubX facilities it
# uses:
#   - sigils only support 32-bit general-purpose registers, so don't work with segment registers or 16-bit or 8-bit registers
#   - metadata like rm32 and r32 can sometimes misleadingly refer to only the bottom 16 bits of the register; pay attention to the register name

# 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 120allocate.subx
# Consult https://wiki.osdev.org/Memory_Map_(x86) before modifying any of this.

== code

## 16-bit entry point

# Upon reset, the IBM PC:
#   - loads the first sector (512 bytes)
#     from some bootable image (look for the boot-sector-marker further down this file)
#     to the address range [0x7c00, 0x7e00)
#   - starts executing code at address 0x7c00

  # disable interrupts for this initialization
  fa/clear-interrupts

  # initialize segment registers
  b8/copy-to-ax 0/imm16
  8e/->seg 3/mod/direct 0/rm32/ax 3/rm32/ds
  8e/->seg 3/mod/direct 0/rm32/ax 0/rm32/es
  8e/->seg 3/mod/direct 0/rm32/ax 4/rm32/fs
  8e/->seg 3/mod/direct 0/rm32/ax 5/rm32/gs

  # 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/copy-to-ax 0x7000/imm16
  8e/->seg 3/mod/direct 0/rm32/ax 2/rm32/ss
  bc/copy-to-esp 0/imm16

  # 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
  {
    e4/read-port-into-al 0x64/imm8
    a8/test-bits-in-al 0x02/imm8  # set zf if bit 1 (second-least significant) is not set
    75/jump-if-!zero loop/imm8
    b0/copy-to-al 0xd1/imm8
    e6/write-al-into-port 0x64/imm8
  }
  {
    e4/read-port-into-al 0x64/imm8
    a8/test-bits-in-al 0x02/imm8  # set zf if bit 1 (second-least significant) is not set
    75/jump-if-!zero loop/imm8
    b0/copy-to-al 0xdf/imm8
    e6/write-al-into-port 0x64/imm8
  }

  # load remaining sectors from first two tracks of disk into addresses [0x7e00, 0x17800)
  b4/copy-to-ah 2/imm8  # read sectors from disk
  # dl comes conveniently initialized at boot time with the index of the device being booted
  b5/copy-to-ch 0/imm8  # cylinder 0
  b6/copy-to-dh 0/imm8  # track 0
  b1/copy-to-cl 2/imm8  # second sector, 1-based
  b0/copy-to-al 0x7d/imm8  # number of sectors to read = 2*63 - 1 = 125
  # address to write sectors to = es:bx = 0x7e00, contiguous with boot segment
  bb/copy-to-bx 0/imm16
  8e/->seg 3/mod/direct 3/rm32/bx 0/r32/es
  bb/copy-to-bx 0x7e00/imm16
  cd/syscall 0x13/imm8/bios-disk-services
  0f 82/jump-if-carry disk_error/disp16

  # load two more tracks of disk into addresses [0x17800, 0x27400)
  b4/copy-to-ah 2/imm8  # read sectors from disk
  # dl comes conveniently initialized at boot time with the index of the device being booted
  b5/copy-to-ch 0/imm8  # cylinder
  b6/copy-to-dh 2/imm8  # track
  b1/copy-to-cl 1/imm8  # sector, 1-based
  b0/copy-to-al 0x7e/imm8  # number of sectors to read = 2*63 = 126
  # address to write sectors to = es:bx = 0x17800, contiguous with boot segment
  bb/copy-to-bx 0x1780/imm16
  8e/->seg 3/mod/direct 3/rm32/bx 0/r32/es
  bb/copy-to-bx 0/imm16
  cd/syscall 0x13/imm8/bios-disk-services
  0f 82/jump-if-carry disk_error/disp16

  # load two more tracks of disk into addresses [0x27400, 0x37000)
  b4/copy-to-ah 2/imm8  # read sectors from disk
  # dl comes conveniently initialized at boot time with the index of the device being booted
  b5/copy-to-ch 0/imm8  # cylinder
  b6/copy-to-dh 4/imm8  # track
  b1/copy-to-cl 1/imm8  # sector, 1-based
  b0/copy-to-al 0x7e/imm8  # number of sectors to read = 2*63 = 126
  # address to write sectors to = es:bx = 0x27400, contiguous with boot segment
  bb/copy-to-bx 0x2740/imm16
  8e/->seg 3/mod/direct 3/rm32/bx 0/r32/es
  bb/copy-to-bx 0/imm16
  cd/syscall 0x13/imm8/bios-disk-services
  0f 82/jump-if-carry disk_error/disp16

  # reset es
  bb/copy-to-bx 0/imm16
  8e/->seg 3/mod/direct 3/rm32/bx 0/r32/es

  # adjust video mode
  b4/copy-to-ah 0x4f/imm8  # VBE commands
  b0/copy-to-al 2/imm8  # set video mode
  bb/copy-to-bx 0x4105/imm16  # 0x0105 | 0x4000
                              # 0x0105 = graphics mode 1024x768x256
                              #  (alternative candidate: 0x0101 for 640x480x256)
                              # 0x4000 bit = configure linear frame buffer in Bochs emulator; hopefully this doesn't hurt anything when running natively
  cd/syscall 0x10/imm8/bios-video-services

  # load information for the (hopefully) current video mode
  # mostly just for the address to the linear frame buffer
  b4/copy-to-ah 0x4f/imm8  # VBE commands
  b0/copy-to-al 1/imm8  # get video mode info
  b9/copy-to-cx 0x0105/imm16  # mode we requested
  bf/copy-to-di Video-mode-info/imm16
  cd/syscall 0x10/imm8/bios-video-services

  ## switch to 32-bit mode
  # load global descriptor table
  # We can't refer to the label directly because SubX doesn't do the right
  # thing for lgdt, so rather than make errors worse in most places we instead
  # pin gdt_descriptor below.
  0f 01/lgdt 2/subop/lgdt 0/mod/indirect 6/rm32/use-disp16 0x7cf8/disp16/gdt_descriptor
  # enable paging
  0f 20/<-cr 3/mod/direct 0/rm32/eax 0/r32/cr0
== data
  # TODO: SubX doesn't understand 66 prefix
#?   66 83/or 3/mod/direct 0/rm32/eax 1/r32/?? 1/imm8  # eax <- or 0x1
  66 83 c8 01  # eax <- or 0x1
== code
  0f 22/->cr 3/mod/direct 0/rm32/eax 0/r32/cr0
  # far jump to initialize_32bit_mode that sets cs to offset 8 in the gdt in the process
  # We can't refer to the label directly because SubX doesn't have syntax for
  # segment selectors. So we instead pin initialize_32bit_mode below.
  ea/jump-far-absolute 0x00087d00/disp32  # address 0x7d00 in offset 8 of the gdt

== data

# 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 00

== code

disk_error:
  # print 'D' to top-left of screen to indicate disk error
  # *0xb8000 <- 0x0f44
  bb/copy-to-bx 0xb800/imm16
  8e/->seg 3/mod/direct 3/rm32/bx 3/r32/ds
  b0/copy-to-al 0x44/imm8/D
  b4/copy-to-ah 0x0f/imm8/white-on-black
  bb/copy-to-bx 0/imm16
  89/<- 0/mod/indirect 7/rm32/bx 0/r32/ax  # *ds:bx <- ax
  # loop forever
  {
    eb/jump loop/disp8
  }

## GDT: 3 records of 8 bytes each
== data

gdt_start:
# offset 0: gdt_null:  mandatory null descriptor
  00 00 00 00 00 00 00 00
# offset 8: gdt_code
  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]
# offset 16: gdt_data
  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:

== data 0x7cf8
gdt_descriptor:
  0x17/imm16  # final index of gdt = size of gdt - 1
  gdt_start/imm32/start

## 32-bit code from this point

== code 0x7d00
initialize_32bit_mode:
== data
  # TODO: SubX doesn't understand 66 prefix
  66 b8 10 00  # ax <- offset 16 from gdt_start
== code
  8e/->seg 3/mod/direct 0/rm32/ax 3/r32/ds
  8e/->seg 3/mod/direct 0/rm32/ax 2/r32/ss
  8e/->seg 3/mod/direct 0/rm32/ax 0/r32/es
  8e/->seg 3/mod/direct 0/rm32/ax 4/r32/fs
  8e/->seg 3/mod/direct 0/rm32/ax 5/r32/gs

  bc/copy-to-esp 0x00070000/imm32

  # load interrupt handlers
  # We can't refer to the label directly because SubX doesn't do the right
  # thing for lidt, so rather than make errors worse in most places we instead
  # pin idt_descriptor below.
  0f 01/lidt 3/subop/lidt 0/mod/indirect 5/rm32/use-disp32 0x8000/disp32/idt_descriptor

  # 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

  # enable keyboard IRQ (1)
  b0/copy-to-al 0xfd/imm8  # disable mask for IRQ1
  e6/write-al-into-port 0x21/imm8

  fb/enable-interrupts
== data
  # TODO: SubX doesn't understand db prefix
  db e3/initialize-floating-point-coprocessor
== code
  # eax <- cr4
  0f 20/<-cr 3/mod/direct 0/rm32/eax 4/r32/cr4
  # eax <- or bit 9
  0f ba/bit-test 5/subop/bit-test-and-set 3/mod/direct 0/rm32/eax 9/imm8
  # cr4 <- eax
  0f 22/->cr 3/mod/direct 0/rm32/eax 4/r32/cr4
== data
  e9 d0 16 00 00  # jump to 0x9400 [label]
== code

== boot-sector-marker 0x7dfe
# final 2 bytes of boot sector
55 aa

## sector 2 onwards loaded by load_disk, not automatically on boot

null-interrupt-handler:
  cf  # iret

# padding
# 201:
   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

== data

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

## the rest of this file is all data

== data 0x8000
idt_descriptor:
  ff 03  # final index of idt = size of idt - 1
  idt_start/imm32/start

# 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

== data 0x8100
Video-mode-info:
# 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
# }}}

== data 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
  null-interrupt-handler/imm16  # target[0:16]
  08 00  # segment selector (gdt_code)
  00  # unused
  8e  # 1/p 00/dpl 0 1110/type/32-bit-interrupt-gate
  0/imm16  # target[16:32] -- null-interrupt-handler must be within address 0x10000

# entry 9: keyboard
  keyboard-interrupt-handler/imm16  # target[0:16]
  08 00  # segment selector (gdt_code)
  00  # unused
  8e  # 1/p 00/dpl 0 1110/type/32-bit-interrupt-gate
  0/imm16  # target[16:32] -- keyboard-interrupt-handler must be within address 0x10000

00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
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:
# }}}

== data 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

== data 0x8700
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

== data 0x8800
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
# }}}

== data 0x8c00
Font:
# 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