Неисправность при попытке jmp после входа в защищенный режим - загрузчик сборки - PullRequest
2 голосов
/ 19 июня 2020

Я весь день пытался в этом разобраться. Я следую руководству по написанию загрузчика, и я застрял, когда дело доходит до правильного входа в защищенный режим. Я не знаю, что делаю не так, и весь день гуглил. Я компилирую с помощью NASM

Это результат, который я получаю в Bochs dbg:

enter image description here

Это говорит о том, что процессор действительно входит в защищенный режим, и вскоре после этого я получаю ошибки. Это вторая переписанная мною работа, направленная прежде всего на то, чтобы войти в защищенный режим без ошибок. Мне бы хотелось, чтобы кто-нибудь мог сказать мне, что я делаю неправильно.

Мой код выглядит следующим образом:

bootloader.asm

global _start

_start:

[bits 16]
[org 0x7c00]

    mov bp, 0x8000
    mov sp, bp

    mov bx, welcomeString
    call print_func


    call print_newline_func

    call switch_to_pm

    jmp $

%include "io.asm"
%include "print.asm"
%include "gdt.asm"

welcomeString:
    db 'Hello. Welcome to OS', 13, 10,0


switch_to_pm:
    cli

    lgdt [gdt_descriptor]
    mov eax, cr0
    or eax, 0x1
    mov cr0, eax


[bits 32]

    jmp CODE_SEG:init_pm


init_pm:

    mov ax, DATA_SEG
    mov ds, ax
    mov ss, ax
    mov es, ax
    mov fs, ax
    mov gs, ax

    mov ebp, 0x90000
    mov esp, ebp

    call BEGIN_PM

BEGIN_PM:
    mov ebx, MSG_PM
    call print_string_pm

    jmp $

MSG_PM:
    db 'success', 0

times 510-($-$$) db 0

dw 0xaa55

io.asm

BOOT_DRIVE:
        db 0

    ReadDisk:                   ; Reads from drive dl amount of sectors to read dh

        push dx                 ; Store dx to stack

        mov ah, 0x02            ; BIOS read sector code
        mov al, dh              ; Read dh sectors
        mov ch, 0x00            ; Select cyl 0
        mov dh, 0x00            ; Select 1st track, 
        mov cl, 0x02            ; Select 2nd sector (1st after boot sector)

        int 0x13                ; Read interrupt code

        jc disk_error           ; Jump if error

        pop dx
        cmp dh, al              ; jump if sectors expected != sectors read
        jne disk_error      

        ret

    errorString:
        db 'Disk Read Error.',13,10,0

    disk_error:
        mov bx, errorString
        call print_func
    ret

gdt.asm

gdt_start:
    gdt_null:       ; null descriptor
        dd 0x0
        dd 0x0

    gdt_code:           ; the code segment descriptor
                        ; base =0x0 , limit =0 xfffff ,
                        ; 1st flags : ( present )1 ( privilege )00 ( descriptor type )1 -> 1001 b
                        ; type flags : ( code )1 ( conforming )0 ( readable )1 ( accessed )0 -> 1010 b
                        ; 2nd flags : ( granularity )1 (32 - bit default )1 (64 - bit seg )0 ( AVL )0 -> 1100 b
        dw 0xffff       ; Limit (bits 0-15)
        dw 0x0          ; Base (bits 0 - 15)
        db 0x0          ; Base (bits 16 - 23)
        db 10011010b    ; 1st flags, type flags
        db 11001111b    ; 2nd flags, limit (bits 16-19)
        db 0x0          ; Base (bits 24-31)

    gdt_data:           ; the data segment descriptor
                        ; Same as code segment except for the type flags :
                        ; type flags : ( code )0 ( expand down )0 ( writable )1 ( accessed )0 -> 0010 b
        dw 0xffff       ; Limit (bits 0-15)
        dw 0x0          ; Base (bits 0-15)
        db 0x0          ; Base (bits 16-23)
        db 10010010b    ; 1st flags, type flags
        db 11001111b    ; 2nd flags
        db 0x0          ; Base (bits 24-31)

    gdt_end:            ; Put this label to calculate size of GDT

gdt_descriptor:
    dw gdt_end - gdt_start - 1      ; GDT size, always 1 less than true size
    dd gdt_start                    ; start address of GDT


CODE_SEG equ gdt_code - gdt_start
DATA_SEG equ gdt_data - gdt_start

print.asm

print_func:
    push bx
        mov ah, 0x0e
        ;add bx, 0x7c00                 ; calculate correct address
        print_loop:
            cmp byte [bx], 0            ; if char at bx == 0, jump to exit.
            je print_exit   
            mov al, [bx]                ; move char at bx into al
            int 0x10                    ; print
            inc bx                      ; increment bx
            jmp print_loop              ; loop to start of func
            print_exit:
            pop bx
                ret

print_newline_func:
    push ax
    mov ah, 0x0e
    mov al, 10
    int 0x10
    mov al, 13
    int 0x10
    pop ax
    ret

print_hex_func:
    push ax
    push bx
    push cx

    mov ah, 0x0e

    mov al, '0'
    int 0x10
    mov al, 'x'
    int 0x10                    ; print 0x          

    ;add bx, 0x7c00

    mov cx, [bx]
    shr cx, 12
    call PrintAsciiFromHex

    mov cx, [bx]
    shr cx, 8
    call PrintAsciiFromHex

    mov cx, [bx]
    shr cx, 4
    call PrintAsciiFromHex

    mov cx, [bx]
    call PrintAsciiFromHex

    pop ax
    pop bx
    pop cx

    ret

PrintAsciiFromHex:
    shl cx, 12
    shr cx, 12
    cmp cx, 9
    jg Add55
    add cx, 48
    jmp Skip
    Add55:
        add cx, 55
    Skip:
    mov al, cl
    int 0x10
    ret

AddressPointer:
    dw 0

PrintAddress:                   ; Moves address of bx into value of AddressPointer
    mov [AddressPointer], bx    ; Passes address of address pointer into bs
    mov bx, AddressPointer      ; prints value of address pointer, therefore printing address
    call print_hex_func
    ret

[bits 32]

                                    ; Define some constants
VIDEO_MEMORY equ 0xb8000
WHITE_ON_BLACK equ 0x0f

                                    ; prints a null - terminated string pointed to by EDX
print_string_pm:
    pusha
    mov edx, VIDEO_MEMORY               ; Set edx to the start of vid mem.
    print_string_pm_loop :
        mov al , [ ebx ]                    ; Store the char at EBX in AL
        mov ah , WHITE_ON_BLACK             ; Store the attributes in AH
        cmp al , 0                          ; if (al == 0) , at end of string , so
        je print_string_pm_done             ; jump to done
        mov [edx] , ax                      ; Store char and attributes at current
                                            ; character cell.
        add ebx , 1                         ; Increment EBX to the next char in string.
        add edx , 2                         ; Move to next character cell in vid mem.

        jmp print_string_pm_loop            ; loop around to print the next char.
    print_string_pm_done :
        popa
        ret                                 ; Return from the function

1 Ответ

4 голосов
/ 19 июня 2020

Решено путем возврата к [битам 16] после 32-битной функции в print.asm и перемещения jmp выше изменения на [биты 32]

...