Downloading the second stage of the bootloader and its launch

Recently, I am trying to understand how bootloaders work. I write my bootloader in nasm assembler and test it with bochs and a floppy image.

Compiled binaries for steps 1 and 2 are combined by copying to a single image. This image is exactly the way I want. 512Bytes stage1 code (magicnumber is enabled and it loads just fine) and 512 stage2 code in the second sector.

But I think that my problem is loading the sector into the plunger and jumping into it. Is there something wrong with my code?

Stage1.asm

BITS 16 start: mov ax, 07C0h ; Set up 4K stack space after this bootloader add ax, 288 ; (4096 + 512) / 16 bytes per paragraph mov ss, ax mov sp, 4096 mov ax, 07C0h ;Set data segment to where we're loaded mov ds, ax mov si,s_version call print_string ; ## Load stage2 mov si,s_loading call print_string xor ax,ax xor bx,bx xor cx,cx xor dx,dx ;read 2nd sector mov ah,02h mov al,1 ;read 1 mov ch,0 ;on track 0 mov cl,2 ;2nd sector mov dh,0 ;head 1 mov dl,0 ;from floppy a mov bx,09C0h;destination segment mov es,bx mov bx,0 ;destination offset int 13h ;<-- Fails right here mov si,s_sector call print_string ;print number of read sectors add ax, 48 mov ah, 0Eh int 10h mov al, 21 mov ah, 0Eh int 10h ;print the sector magicnumber (debugging purposes) mov al, [09C0h+511] int 10h xor ax,ax int 16h mov si,s_jumping call print_string call word 09C0h:0000h ; #### print a string from si print_string: push ax push bx mov ah, 0Eh .repeat: lodsb cmp al, 0 je .exit int 10h jmp .repeat .exit: pop bx pop ax ret ; **** ; #### define strings s_version db 'VeOS 0.0.0.1',10,13,0 s_loading db 'Loading Stage2...',10,13,0 s_sector db 'Loading sector...',10,13,0 s_jumping db 'Passing control to Stage2.',10,13,0 ; **** ;fillup with zeros times 510-($-$$) db 0 ;boot signature dw 0xAA55 

stage2.asm

 BITS 16 start: mov ax, 09C0h ; Set up 4K stack space after this bootloader add ax, 288 ; (4096 + 512) / 16 bytes per paragraph mov ss, ax mov sp, 4096 mov ax, 09C0h ;Set data segment to where we're loaded mov ds, ax mov ah, 0Eh mov al, 21 ;"!" int 10h mov ah, 00h int 16h jmp $ times 511-($-$$) db 0 ;Magicnumber for debugging db 0x41 

I carefully sorted into Google and did not find anything that accurately describes how to load a sector into a plunger and jump into it. My program is also not listed in Magicnumber of the 2nd sector.

It would be great if it was just a miscalculation of addresses.

Update: The current source code, the line in which it has a lock, is marked. I set all 4 main registers to 0 from pure paranoia.

Update2: Again the current version. Nothing happens between setting registers and issuing int 13h.

+4
source share
1 answer

Update: In addition to the one below, you also overwrite your stack at boot time!

Your stack is at 07C0h + 288 : 4096 , which is 08E0h:1000h = 09E0h:0000h , and you read 09C0h:0000 and 512 bytes ahead (ending in 09E0h:0000h ), overwriting the stack. Move your stack or read to another place. See osdev.org Memory Card for inspiration.

I'm afraid I don’t know a good step-by-step debugger. I just put the jmp $-2 instruction in the code and used the built-in QEMU debugger to create “information registers” at the corresponding points. I think Boch might have something similar.

Three (2.5) things that I see (although there may be more):

 ;read 2nd sector mov ah,02h mov al,1 ;read 1 mov ch,0 ;on track 0 mov cl,1 ;2nd sector mov dl,0 ;from floppy a mov bx,09C0h ;destination mov es,bx int 13h 
  • You leave bx as 09c0h , so it will read 09C0h:09C0h , not 09C0h:0000h .
  • You say that you are reading from the second sector ( cl = 1 ), but you are reading from the first !. See Ralph Brown .
  • You do not set dh (head). This is probably good in Bochs, but I can’t remember with what initial conditions it is guaranteed, except for dl set to the disk number .

Here's the bootloader that I used for a small test kernel (parts taken from different parts of osdev.org may have errors that I presented, so be careful) if you want to compare / copy. (I leave the dl intact because it contains a boot disk, so you don't need to hardcode it).

  bits 16 org 0x7c00 Start: jmp EntryPoint PrintString16: pusha .PrintLoop: lodsb or al, al jz .PrintDone mov ah, 0xe int 0x10 jmp .PrintLoop .PrintDone: popa ret EntryPoint: xor ax, ax mov ss, ax mov ds, ax mov sp, 0x7c00 .DiskReset: mov ah, 0 int 0x13 jc .DiskReset mov ax, 0x50 ; load to 0x500 linear address. It has unused space up to 0x7bff mov es, ax xor bx, bx mov ax, 0x023B ; count = 0x3b = 59, the maximum (while still leaving soom room for the stack and the boot sector code we're currently running) mov cx, 0x0002 xor dh, dh ; leave dl intact int 0x13 jnc .ReadDone mov si, ReadError call PrintString16 jmp .DiskReset .ReadDone: ;jmp 0x50:0x0 ;jump to stage 2 loaded at 0x500 cli xor ax, ax mov ds, ax mov es, ax mov ax, 0x9000 mov ss, ax mov sp, 0xffff sti mov si, HelloMsg call PrintString16 ; Disable interrupts until safely in protected mode cli ; Install GDT lgdt [toc] ; Enable A20 mov al, 0xdd out 0x64, al mov si, GoPMode call PrintString16 ; enable protected mode mov eax, cr0 or eax, 1 mov cr0, eax jmp 0x8:PmodeStart bits 32 PmodeStart: ; setup stack and datasegments mov ax, 0x10 mov ds, ax mov es, ax mov fs, ax mov gs, ax mov ss, ax ; Setup stack at 0x90000 mov esp, 0x90000 ; Jump to C-code jmp 0x8:0x500 ; Reboot if C-code returns Reboot: mov word [0x472], 0x1234 jmp 0x8:0xffff0 ReadError db 'Read error - retrying...', 13, 10, 0 HelloMsg db 'Loading...',0 GoPMode db 'Entering protected mode..',0 gdt_data: dd 0 ; null descriptor dd 0 ; gdt code: ; code descriptor dw 0FFFFh ; limit low dw 0 ; base low db 0 ; base middle db 10011010b ; access db 11001111b ; granularity db 0 ; base high ; gdt data: ; data descriptor dw 0FFFFh ; limit low (Same as code)10:56 AM 7/8/2007 dw 0 ; base low db 0 ; base middle db 10010010b ; access db 11001111b ; granularity db 0 ; base high end_of_gdt: toc: dw end_of_gdt - gdt_data - 1 ; limit (Size of GDT) dd gdt_data ; base of GDT times 510 - ($-$$) db 0 ; pad to 512 bytees, will also warn if we exceed 512 bytes dw 0xAA55 ; boot signature 
+3
source

All Articles