blob: e8b1f21a08096e6065492d829e48b736795e4c59 (
plain) (
tree)
|
|
# Bootable image demonstrating printing to screen in 32-bit mode.
# Must have exactly 512 bytes.
#
# To convert to a disk image:
# ./bootstrap run apps/hex < apps/bos/32bit.hex > boot.bin
# To run:
# qemu-system-i386 boot.bin
# Or:
# bochs -f apps/bos/bochsrc # bochsrc loads boot.bin
#
# Expected output inside emulator:
# H
## 16-bit entry point
# Boot image starts executing at address 0x7c00,
# and so occupies [0x7c00, 0x7e00).
# We don't read or write the stack before we get to 32-bit mode.
# 00:
fa # cli # TODO: don't forget to reenable interrupts at some point
0f 01 16 # lgdt 00/mod/indirect 010/subop 110/rm32/TODO
80 7c # *gdt_descriptor
0f 20 c0 # eax <- cr0
66 83 c8 01 # eax <- or 0x1
0f 22 c0 # cr0 <- eax
ea c0 7c 08 00 # far jump to initialize_32bit_mode after setting cs to the record at offset 8 in the gdt (gdt_code)
# padding
# 15:
00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
## GDT: 3 records of 8 bytes each
# 60:
# 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:
# padding
# 78:
00 00 00 00 00 00 00 00
# 80:
# gdt_descriptor:
17 00 # final index of gdt = gdt_end - gdt_start - 1
60 7c 00 00 # start = gdt_start
# padding
# 85:
00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
## 32-bit code from this point (still some instructions not in SubX)
# c0:
# 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
e9 1d 00 00 00 # jump to 0x7cf0
# padding
# d3:
00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
## 'application' SubX code: print one character to top-left of screen
# f0:
# Entry:
# *0xb8000 <- 0x0f48
c7 # opcode
# modrm
05 # 00/mod/indirect 000/subop/copy 101/rm32/use-disp32
# disp32
00 80 0b 00
# imm32
48 # 'H'
0f # white on black
00 00
e9 fb ff ff ff # loop forever
# padding to 512 bytes
00
# 100:
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00
55 aa # final 2 bytes: boot sector marker
# vim:ft=subx
|