Skip to content

Instantly share code, notes, and snippets.

@akesterson
Created January 25, 2015 02:26
Show Gist options
  • Save akesterson/5eb9b223db4cfa3d22d4 to your computer and use it in GitHub Desktop.
Save akesterson/5eb9b223db4cfa3d22d4 to your computer and use it in GitHub Desktop.
8086 bootloader / kernel "load from disk and jump to kernel" problem
##### First we build from scratch ...
#######################################
akesterson@akesterson-pc:~/source/upstream/git/akesterson/piquant$ make clean all
rm -f boot.bin asm/*o src/*o
bcc -ansi -3 -c -o src/kernel.o src/kernel.c
ld86 -T0x1000 -M -o kernel.bin src/kernel.o
kernel _printString 0 0000101b R
kernel _main 0 00001049 R
kernel _printChar 0 00001000 R
Total memory used: 00000108
objdump86 kernel.bin | \
grep -E "^[0-9]+ T _.*" | \
python -c "import sys; print '\n'.join([\"_extern_c%s:\n jmp 0x1000:0x%04x\" % (x.split(' ')[2].strip('\n'), int(x.split(' ')[0].lstrip('0'), 16)-0x1000) for x in sys.stdin.readlines()])" > asm/kernel_syms.S
cd asm && nasm bootloader.S -f bin -o ../boot.bin
cat boot.bin kernel.bin > boot.img
#######################################
#### TL;DR bootloader.S is supposed to load the
#### kernel.bin (from kernel.c) off the floppy
#### and jump to it.
#######################################
mov al, 0x1 ; read the remaining 16 tracks
mov ch, 0x0 ; .... on track 0 ....
mov cl, 0x2 ; .... starting at sector 2
mov bx, 0x1000 ; 0x1000 is a standard kernel start location
mov es, bx
mov bx, 0x0 ; bx = 0, es:bx = 0x1000:0
call loadFloppyDiskSectors
;; ... snip ...
jmp _extern_c_main
#######################################
#### _extern_c_main is constructed from the symbol table of kernel.bin
#### and contains the (or what should be) the addresses of all functions
#### built into kernel.bin from kernel.c
####
#### Here's the contents of asm/kernel_syms.S, the Makefile rebuilds it
#### every time kernel.bin changes:
#######################################
_extern_c_main:
jmp 0x1000:0x0049
_extern_c_printCh:
jmp 0x1000:0x0000
########################################
##### But instead of jumping to main() and looping forever (as expected),
##### Bochs reaches what appears to be uninitialized RAM, and I'm not sure
##### my code is doing what I expect. Consider:
#########################################
bochs -f bochsrc -q
( .... snip .. )
Next at t=0
(0) [0x0000fffffff0] f000:fff0 (unk. ctxt): jmp far f000:e05b ; ea5be000f0
<bochs:1> break 0x7c00
<bochs:2> c
( ... snip ... )
(0) Breakpoint 1, 0x00007c00 in ?? ()
Next at t=14040381
( ... snip ... )
####################################################
#### THe disk load goes as expected, or appears to,
#### loading the kernel.bin into 0x1000:0000 (es:bx)
####################################################
(0) [0x000000007c16] 0000:7c16 (unk. ctxt): mov al, 0x01 ; b001
<bochs:11>
Next at t=15548283
(0) [0x000000007c18] 0000:7c18 (unk. ctxt): mov ch, 0x00 ; b500
<bochs:12>
Next at t=15548284
(0) [0x000000007c1a] 0000:7c1a (unk. ctxt): mov cl, 0x02 ; b102
<bochs:13>
Next at t=15548285
(0) [0x000000007c1c] 0000:7c1c (unk. ctxt): mov bx, 0x1000 ; bb0010
<bochs:14>
Next at t=15548286
(0) [0x000000007c1f] 0000:7c1f (unk. ctxt): mov es, bx ; 8ec3
<bochs:15>
Next at t=15548287
(0) [0x000000007c21] 0000:7c21 (unk. ctxt): mov bx, 0x0000 ; bb0000
<bochs:16>
Next at t=15548288
(0) [0x000000007c24] 0000:7c24 (unk. ctxt): call .+24 (0x00007c3f) ; e81800
<bochs:17>
00015548964i[FDD ] partial read() on floppy image returns 168/512
Next at t=17014567
(0) [0x000000007c27] 0000:7c27 (unk. ctxt): mov dh, 0x01 ; b601
######## So let's dump the memory there and check it out...
<bochs:18> writemem "bum   dump.com   bin" 0x1000 6555 35          00010000 65535
00000000 01 03 10 10 20 00 00 00 58 00 00 00 00 00 00 00 |.... ...X.......|
00000010 00 00 00 00 00 00 00 00 58 90 00 00 30 00 00 00 |........X...0...|
00000020 66 89 e3 67 66 8b 77 02 b4 0e b7 00 b3 07 cd 10 |f..gf.w.........|
00000030 55 89 e5 57 56 53 5b 5e 5f 5d c3 55 89 e5 57 56 |U..WVS[^_].U..WV|
00000040 53 eb 18 8b 5d 08 8a 03 0f b6 c0 50 e8 cf ff ff |S...]......P....|
00000050 ff 83 c4 04 8b 5d 08 43 89 5d 08 8b 5d 08 8a 03 |.....].C.]..]...|
00000060 84 c0 75 df 5b 5e 5f 5d c3 55 89 e5 57 56 53 eb |..u.[^_].U..WVS.|
00000070 fe 5b 5e 5f 5d c3 00 00 5f 70 72 69 6e 74 53 74 |.[^_]..._printSt|
00000080 1b 10 00 00 12 00 00 00 5f 6d 61 69 6e 00 00 00 |........_main...|
00000090 49 10 00 00 12 00 00 00 5f 70 72 69 6e 74 43 68 |I......._printCh|
000000a0 00 10 00 00 12 00 00 00 00 00 00 00 00 00 00 00 |................|
000000b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
0000ffff
######################################################################
####### Yep, there's our kernel. So we should jump to main() directly ... right?
######################################################################
(0) [0x000000007c34] 0000:7c34 (unk. ctxt): jmp .+66 (0x00007c78) ; eb42
<bochs:24>
Next at t=17024678
(0) [0x000000007c78] 0000:7c78 (unk. ctxt): jmp far 1000:0049 ; ea49000010
<bochs:25>
Next at t=17024679
(0) [0x000000010049] 1000:0049 (unk. ctxt): mov dh, 0xc0 ; b6c0
<bochs:26>
Next at t=17024680
(0) [0x00000001004b] 1000:004b (unk. ctxt): push ax ; 50
<bochs:27>
Next at t=17024681
(0) [0x00000001004c] 1000:004c (unk. ctxt): call .-49 (0x0001001e) ; e8cfff
<bochs:28>
Next at t=17025395
(0) [0x00000001004f] 1000:004f (unk. ctxt): (invalid) ; ffff
################################################
#### What the hell? that was not my main() !!!!
#### What am I doing wrong?
################################################
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment