Can't jump or call kernel loaded at 0x8000

南楼画角 提交于 2019-12-01 03:32:44

问题


I am trying to develop an operating system. The design is this: I have a bootloader loaded at 0x7c00 which loads the second stage and jumps to it at 0x7e00. The second stage is also in real mode and does a lot of stuff such as loading gdt, enabling A20 and switching to protected mode. It also loads a very simple 32 bit kernel at 0x8000. The problem now is that I am not able to call or jmp to 0x8000 as the kernel doesn't seem to get loaded(I did a memory dump in VirtualBox). I have already done a FAR JMP within the second stage to set the CS register. I am testing my OS in VirtualBox.

Code for my boot loader:

org 0x7c00
bits 16
Start:
      jmp Reset
      bpbOEM DB "SKULLOS " 
      bpbBytesPerSector:    DW 512
      bpbSectorsPerCluster:     DB 1
      bpbReservedSectors:   DW 1
      bpbNumberOfFATs:      DB 2
      bpbRootEntries:       DW 224
      bpbTotalSectors:      DW 2880
      bpbMedia:                 DB 0xF0
      bpbSectorsPerFAT:         DW 9
      bpbSectorsPerTrack:   DW 18
      bpbHeadsPerCylinder:  DW 2
      bpbHiddenSectors:         DD 0
      bpbTotalSectorsBig:     DD 0
      bsDriveNumber:            DB 0
      bsUnused:                 DB 0
      bsExtBootSignature:   DB 0x29
      bsSerialNumber:           DD 0xa0a1a2a3
      bsVolumeLabel:            DB "MOS FLOPPY "
      bsFileSystem:             DB "SKFS    "
Set:
      mov al , 02h
      mov ah , 00h
      int 10h
      jmp Print
Print:
      mov al , 'A'
      mov bl , 0Fh
      mov cx , 01h
      mov ah , 09h
      int 10h
      jmp Reset
Reset:
      ; mov dl , 0x00
        mov [0x500] , dl
        mov ah , 0x00
        int 0x13
        jc Reset
        mov ax , 0x7E0 
        mov es , ax
        xor bx , bx
        mov ah , 0x02
        mov al , 1
        mov ch , 0
        mov cl , 2
        mov dh , 0
        mov dl , [0x500]
        int 0x13
        jmp 0x0000 :0x7e00
        times 510-($-$$) db 0
        db 0x55
        db 0xAA

Code for second stage:

    org 0x7E00
    bits 16
    Start:
          jmp Setup
    ;;;;;;;;;;;;;stack;;;;;;;;;;
    Setup: 
          cli
          xor ax , ax
          mov ds , ax
          mov es , ax
          mov ax , 0x9000
          mov ss , ax
          mov sp , 0xFFFF
          sti
          jmp Set
   ;;;;;;;;;;;;;video;;;;;;;;;;;
   Set: 
          mov al , 03h
          mov ah , 00h
          int 10h
          mov ah , 09h
          mov al , 'A'
          mov bh , 00h
          mov bl , 0x0F
          mov cx , 01h
          int 10h
          jmp loadgdt
   ;;;;;;;;;;;;gdt;;;;;;;;;;;;;;;
   gdt_start:
   null: 
          dd 0
          dd 0
   code:
          dw 0FFFFh
          dw 0
          db 0
          db 10011010b
          db 11001111b
          db 0
   data:
          dw 0FFFFh
          dw 0
          db 0
          db 10010010b
          db 11001111b
          db 0
   end:
   load: dw end - gdt_start -1
         dd null
   ;;;;;;;;;;;;;loadgdt;;;;;;;;;;
   loadgdt:
         lgdt [load]
         jmp A20
   ;;;;;;;;;;;;A20;;;;;;;;;;;;;;;
   A20:
         mov ax , 0x2401
         int 0x15
         jc A20
         jmp Reset
   ;;;;;;;;;;;;;floppy;;;;;;;;;;;
   Reset:
         mov ah , 00h
         mov dl , [0x500]
         int 13h
         jc Reset
         jmp Read
   Read:
         mov ah , 02h
         mov al , 01h
         mov ch , 00h
         mov cl , 03h
         mov dh , 00h
         mov dl , [0x500]
         mov ax , 0x800
         mov es , ax
         xor bx , bx
         int 13h
         jc Read
         jmp Begin
   Begin:  
         mov ah , 09h
         mov al , 'G'
         mov bh , 00h
         mov bl , 0x0F
         mov cx , 01h
         int 10h
         jmp protected
   ;;;;;;;;;;;switching to protected;;;;
   protected: 
             mov ah , 09h
             mov al , 'P'
             mov bh , 00h
             mov bl , 0x0F
             mov cx , 01h
             int 10h
             xor ax, ax
             mov ds, ax    
             cli
             mov eax, cr0
             or eax , 1
             mov cr0 , eax
             jmp (code-gdt_start):transfer_control
   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   bits 32 
   transfer_control:
                    mov ax, (data-gdt_start)        
                    mov ds, ax
                    mov ss, ax
                    mov es, ax
                    mov esp, 90000h
                    mov [0xB8000], word 0x0F58  ; Print 'X' 
                    call 0x8000    
                    hlt
   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   times 512-($-$$) db 0

Code for kernel:

org 0x8000
bits 32
jmp Start
Start:
      mov ax , 0x10
      mov ds , ax
      mov ss, ax
      mov es, ax
      mov esp, 90000h
      mov [0xB8002], word 0x0F58   ; Print 'X'
      ret
times 512-($-$$) db 0

Currently, only one 'X' is being printed. However, two 'X' should be printed. Commands used to create floppy:

      dd seek=0 if=boot of=os.img
      dd seek=1 if=second_stage of=os.img
      dd seek=2 if=third_stage of=os.img


回答1:


Problem Reading Stage 3

In the second stage you load the third stage doing this:

   Read:
         mov ah , 02h      ; Setup AH
         mov al , 01h      ; Setup AL
         mov ch , 00h
         mov cl , 03h
         mov dh , 00h
         mov dl , [0x500]
         mov ax , 0x800    ; Destroy contents of AX 
         mov es , ax       ; Setup ES=0x800
         xor bx , bx
         int 13h

I have marked the lines with the problems. You effectively set up AX to get ready for the read and then overwrite the values with 0x800 to set up ES. Move setting up ES before you setup AH and AL. Modify the code to look like:

   Read:
         mov ax , 0x800 
         mov es , ax       ; Setup ES=0x800
         mov ah , 02h      ; Setup AH
         mov al , 01h      ; Setup AL
         mov ch , 00h
         mov cl , 03h
         mov dh , 00h
         mov dl , [0x500]
         xor bx , bx
         int 13h

This likely prevents your second stage from loading the 3rd stage properly.


Other Issues

At the end of the bootloader you have:

    db 0xAA
    db 0x55

This is backwards and should be:

    db 0x55
    db 0xAA

You could have written it as:

    dw 0xAA55

The issue appears to be that you didn't take little endianness into account when defining these bytes.


You properly jump over the BIOS Parameter Block in the bootloader, but the BPB needs to start at the 4th byte in the boot sector. You can force a 2-byte JMP using the short modifier. You can then place a nop after the jump so that the BPB starts at the 4th byte.

Change:

  jmp Reset
  bpbOEM DB "SKULLOS " 

To:

  jmp short Reset
  nop         ; 1 byte padding as BPB needs to start at 4th byte (short jmp takes 2 bytes)
  bpbOEM DB "SKULLOS " 

mov sp , 0xFFFF should probably be mov sp, 0x0000. This is just a minor nitpick. Having the stack on a WORD boundary (even addresses) performs better on 8086 processors. Since you are not in real mode very long it doesn't much matter at all. Usually you'd use mov sp, 0x0000 in your case because the first WORD pushed will be at 0x9000:0xfffe since 2 is subtracted from SP first and then the WORD pushed onto the stack. Effectively with SP=0x0000 the stack will start by wrapping to the top of the 64k segment.


You don't need to JMP from label to label if the label is right after the JMP. Instructions like:

    jmp Set 
Set: 

does nothing but waste space and take CPU cycles. I noticed you did that in quite a few places. This isn't part of your problem, just an observation. The FAR JUMP jmp (code-gdt_start):transfer_control followed by the label is fine since that is used to to set the CS descriptor properly (for protected mode)


When doing disk access with int 13h you should be using the boot drive number passed by the BIOS to your bootloader as the value for DL. Your first and second stages have code like:

mov dl , 00h

This always assumes you are reading from the first floppy (A:). If you want to use your code on a boot drive other than Floppy A: you'll want to remove this



来源:https://stackoverflow.com/questions/34636538/cant-jump-or-call-kernel-loaded-at-0x8000

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!