开发者

Loading 2nd stage of bootloader and starting it [duplicate]

This question already has answers here: How to load second stage boot loader from first stage? (3 answers) Legacy BIOS bootloader to bootstrap real-mode code in second stage (2 answers) Closed 7 years ago.

Recently I'm trying to get a hang on how bootloaders work. I'm writing my loader in nasm assembler and test it with bochs and a floppy image.

The compiled binaries for stage 1 and 2 get joined via copy into one image. This image is exactly as I want it. 512Bytes stage1 code (magicnumber included and it loads just fine) and 512 stage2 code in the 2nd sector.

But I think my problem is loading the sector into the ram 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
开发者_如何学Python    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's 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 googled thoroughly and found nothing describing exactly how to load a sector into the ram and jump into it. Not even the Magicnumber of the 2nd sector is found by my programm.

Would be great if it is just some miscalculation on the addresses.

Update: Current sourcecode, the line where it has a lockup is marked. I set all 4 main registers to 0 out of pure paranoia.

Update2: Again the current version. No stuff done between setting up the registers and issuing int 13h.


Update: In addition to the below, you're also overwriting your stack when you load!

Your stack is located at 07C0h + 288 : 4096 which is 08E0h:1000h = 09E0h:0000h, and you're reading to 09C0h:0000, and 512 bytes forward (ending at 09E0h:0000h) overwriting the stack. Either move your stack or read to some other place. See the memory map from osdev.org for inspiration.

I'm afraid I don't know a good step-by-step debugger. I just placed a jmp $-2 instruction in the code and used QEMUs built-in debugger to do "info registers" at appropriate points. I think Bochs might have something similar.

Three (2.5) things I see (though there might 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're leaving bx as 09c0h, so it will read to 09C0h:09C0h rather than 09C0h:0000h.
  • You say you're reading from the second sector (cl = 1), but you're reading from the first!. See Ralph Brown.
  • You're not setting dh (head). It's probably fine in Bochs, but I can't recall off the top of my head what initial conditions are guaranteed apart from dl being set to the drive number.

Here's the boot loader I've used for a small test kernel (parts taken from various parts of osdev.org and might have errors I've introduced, so be careful), if you wish to compare/copy. (I leave dl intact because it contains the boot drive so you don't have to hard code 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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜