C语言 无法加载我的操作系统内核



我正在尝试用C开发一个内核。我的内核应该显示一条非常简单的欢迎消息。引导加载程序的第二阶段在0x8000加载内核,并将内核移动到0x100000。我的内核由两部分组成。 third_stage.asm调用 os.c 中的主函数。问题是我不断得到上师冥想错误。

我的引导加载程序(boot)的代码可以在我之前的StackOverflow问题中找到。

我第二阶段的代码:

  org 0x7E00
  bits 16
  ;;;;;;;;;;;;;stack;;;;;;;;;;
  Setup: 
        cli
        xor ax , ax
        mov ds , ax
        mov es , ax
        mov ax , 0x9000
        mov ss , ax
        mov sp , 0x0000
        sti
 ;;;;;;;;;;;;;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]
    ;;;;;;;;;;;;A20;;;;;;;;;;;;;;;
    A20:
         mov ax , 0x2401
         int 0x15
         jc A20
    ;;;;;;;;;;;;;floppy;;;;;;;;;;;
    Reset:
          mov ah , 00h
          mov dl , [0x500]
          int 13h
          jc Reset
    Read:
          mov ax , 0x800 
          mov es , ax       ; Setup ES=0x800
          mov ah , 02h      ; Setup AH
          mov al , 0fh      ; Setup AL
          mov ch , 00h
          mov cl , 03h
          mov dh , 00h
          mov dl , [0x500]
          xor bx , bx
          int 13h
          jc Read
   Begin:  
           mov ah , 09h
           mov al , 'G'
           mov bh , 00h
           mov bl , 0x0F
           mov cx , 01h
           int 10h
   ;;;;;;;;;;;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' 
           CopyImage: 
                            mov eax , dword 0x0f
                            mov ebx , dword 0x200
                            mul ebx
                            mov ebx , 4
                            div ebx
                            cld
                            mov esi , 0x8000
                            mov edi , 0x100000
                            mov ecx , eax
                            rep movsd
                            jmp 0x100000  
          ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
           times 512-($-$$) db 0

third_stage代码:

bits 32
global _start
extern main
_start:
       mov ax , 0x10
       mov ds , ax
       mov ss, ax
       mov es, ax
       mov esp, 90000h
       mov [0xB8002], word 0x0F58   ; Print 'X'
       call main      
       hlt   

操作系统代码:

//reserved - 0x500(drive number), 0x501(keyboard buffer), 0x502(screen X) , 0x503(screen y) 
volatile char * buffer = (volatile char*)0x501 ;
volatile char * x = (volatile char*)0x502 ;
volatile char * y = (volatile char*)0x503 ;
void newline() {
if(*y < 24) {
*y++ ;
*x = 0 ;
}
else {
*y = 25 ;
*x = 80 ;
}
}
void clrscr() {
volatile char * display = (volatile char*)0xb8000 ; 
for(display = 0xb8000 ; display <= 0xbffff;display++) {
*display = 0  ;
} 
}
 void println(char output[]) {
 char * x = (char*)0x502 ;
 char * y = (char*)0x503 ;
 int arg = 0 ;
 if(*x == 80 && *y == 25) {
 clrscr() ;
 *x = 0 ;
 *y = 0 ;
 }
 volatile char * display = (volatile char*)0xb8000 + (((*y * 80) + *x) * 2) ;
 while(output[arg] != '') {
  if(*x == 80 && *y == 25) {
  clrscr() ;
   *x = 0 ;
   *y = 0 ;
    arg = 0 ;
    display = 0xb8000 ;
 }
   else if(*x == 80) {
   *y++ ;
   *x = 0 ;
    }
   *display = output[arg] ;
    display++ ;
   *display = 0x0f ;
    display++ ;
    arg++ ;
    *x++ ;
    }
    newline() ; 
    }
    void print(char output[]) {
    int arg = 0 ;
    if(*x == 80 && *y == 25) {
    clrscr() ;
    *x = 0 ;
    *y = 0 ;
    }
    volatile char * display = (volatile char*)0xb8000 + (((*y * 80) + *x) * 2) ;
   while(output[arg] != '') {
   if(*x == 80 && *y == 25) {
   clrscr() ;
   *x = 0 ;
   *y = 0 ;
   arg = 0 ;
   display = 0xb8000 ; 
   }
   else if(*x == 80) {
   *y++ ;
   *x = 0 ;
   }
   *display = output[arg] ;
    display++ ;
   *display = 0x0f ;
    display++ ;
    arg++ ;
    *x++ ;
  } 
  }
  void printc(char output) {
   char * x = (char*)0x502 ;
   char * y = (char*)0x503 ;
   if(*x == 80 && *y == 25) {
   clrscr() ;
    *x = 0 ;
    *y = 0 ;
    }
     else if(*x == 80) {
     *y++ ;
     *x = 0 ;
    }
    volatile char * display = (volatile char*)0xb8000 + (((*y * 80) + *x) * 2) ;
    *display = output ;
     display++ ;
    *display = 0x0f ;
     display++ ;
     *x++ ;
     if(*x == 80) {
     *y++ ;
     *x = 0 ;
     }
     }
     void backspace() {
     if(*x == 0 && *y == 0) {
     }
     else if(*x == 0) {
     *x = 79 ;
     *y-- ;
      volatile char * display = (volatile char*)0xb8000 + (((*y * 80) + *x) * 2) ;
      *display = 0 ;
       display++ ;
      *display = 0 ;
     }
      else {
      *x-- ;
      volatile char * display = (volatile char*)0xb8000 + (((*y * 80) + *x) * 2) ;
      *display = 0 ;
       display++ ;
       *display = 0 ;
     }
     }
     char * scanln() {
     static char input[512] ;
     char scancode[0xd9] ;
     char shift_scancode[0xd9] ;
     *buffer = 0 ;
      int arg = 0 ;
      scancode[0x1c] = 'a' ;
      scancode[0x32] = 'b' ;
      scancode[0x21] = 'c' ;
      scancode[0x23] = 'd' ;
      scancode[0x24] = 'e' ;
      scancode[0x2b] = 'f' ;
      scancode[0x34] = 'g' ;
      scancode[0x33] = 'h' ;
      scancode[0x43] = 'i' ;
      scancode[0x3b] = 'j' ;
      scancode[0x42] = 'k' ;
      scancode[0x4b] = 'l' ;
      scancode[0x3a] = 'm' ;
      scancode[0x31] = 'n' ;
      scancode[0x44] = 'o' ;
      scancode[0x4d] = 'p' ;
      scancode[0x15] = 'q' ;
      scancode[0x2d] = 'r' ;
      scancode[0x1b] = 's' ;
      scancode[0x2c] = 't' ;
      scancode[0x3c] = 'u' ;
      scancode[0x2a] = 'v' ;
      scancode[0x1d] = 'w' ;
      scancode[0x22] = 'x' ;
      scancode[0x35] = 'y' ;
      scancode[0x1a] = 'z' ;
      scancode[0x45] = '0' ;
      scancode[0x16] = '1' ;
      scancode[0x1e] = '2' ; 
      scancode[0x26] = '3' ;
      scancode[0x25] = '4' ;
      scancode[0x2e] = '5' ;
      scancode[0x36] = '6' ;
      scancode[0x3d] = '7' ;
      scancode[0x3e] = '8' ;
      scancode[0x46] = '9' ;
      scancode[0x0e] = '`' ;
      scancode[0x4e] = '-' ;
      scancode[0x55] = '=' ;
      scancode[0x5d] = '\' ;
      scancode[0x54] = '[' ;
      scancode[0x5b] = ']' ;
      scancode[0x4c] = ';' ;
      scancode[0x52] = ''' ;
      scancode[0x41] = ',' ;
      scancode[0x49] = '.' ;
      scancode[0x4a] = '/' ;
      scancode[0x29] = ' ' ;
      shift_scancode[0x1c] = 'A' ;
      shift_scancode[0x32] = 'B' ;
      shift_scancode[0x21] = 'C' ;
      shift_scancode[0x23] = 'D' ;
      shift_scancode[0x24] = 'E' ;
      shift_scancode[0x2b] = 'F' ;
      shift_scancode[0x34] = 'G' ;
      shift_scancode[0x33] = 'H' ;
      shift_scancode[0x43] = 'I' ;
      shift_scancode[0x3b] = 'J' ;
      shift_scancode[0x42] = 'K' ;
      shift_scancode[0x4b] = 'L' ;
      shift_scancode[0x3a] = 'M' ;
      shift_scancode[0x31] = 'N' ;
       shift_scancode[0x44] = 'O' ;
      shift_scancode[0x4d] = 'P' ;
      shift_scancode[0x15] = 'Q' ;
      shift_scancode[0x2d] = 'R' ;
      shift_scancode[0x1b] = 'S' ;
      shift_scancode[0x2c] = 'T' ;
      shift_scancode[0x3c] = 'U' ;
      shift_scancode[0x2a] = 'V' ;
       shift_scancode[0x1d] = 'W' ;
      shift_scancode[0x22] = 'X' ;
      shift_scancode[0x35] = 'Y' ;
      shift_scancode[0x1a] = 'Z' ;
      shift_scancode[0x45] = ')' ;
      shift_scancode[0x16] = '!' ;
      shift_scancode[0x1e] = '@' ;
      shift_scancode[0x26] = '#' ;
      shift_scancode[0x25] = '$' ;
      shift_scancode[0x2e] = '%' ;
      shift_scancode[0x36] = '^' ;
      shift_scancode[0x3d] = '&' ;
      shift_scancode[0x3e] = '*' ;
      shift_scancode[0x46] = '(' ;
      shift_scancode[0x0e] = '~' ;
      shift_scancode[0x4e] = '_' ;
       shift_scancode[0x55] = '+' ;
      shift_scancode[0x5d] = '|' ;
      shift_scancode[0x54] = '{' ;
       shift_scancode[0x5b] = '}' ;
      shift_scancode[0x4c] = ':' ;
      shift_scancode[0x52] = '"' ;
      shift_scancode[0x41] = '<' ;
      shift_scancode[0x49] = '>' ;
       shift_scancode[0x4a] = '?' ;
      shift_scancode[0x29] = ' ' ;
      while(*buffer != 0x5a) {
      if(*buffer == 0x12) {
       *buffer = 0 ;
      if(shift_scancode[(int)*buffer] != 0) {
      input[arg] = shift_scancode[(int)*buffer] ;
      printc(shift_scancode[(int)*buffer]) ;
      *buffer = 0  ;
      arg++ ;
    }
    if(*buffer == 0xf0) {
    *buffer = 0 ;
    *buffer = 0 ;
   } 
   }
    else if(*buffer == 0xf0) {
    *buffer = 0 ;
     *buffer = 0 ;
   }
   else if(*buffer == 0x66) {
   arg-- ;
   if(arg >= 0) {
    backspace() ;
    }
     else {
     arg = 0 ;
    }
    }
    else if(scancode[(int)*buffer] != 0) {
    input[arg] = scancode[(int)*buffer] ;
     printc(scancode[(int)*buffer]) ;
    *buffer = 0 ;
     arg++ ;
    }
    }
    input[arg] = '' ;
    *buffer = 0 ;
    *buffer = 0 ;
     return input ;
    }
    void main() {
    char * x = (char*)0x502 ;
    char * y = (char*)0x503 ;
    *x = 0 ;
    *y = 0 ;
    println("------------------------------Welcome to Skull OS------------------------------") ;
    println("Boot Successful") ;
   }      

用于制作操作系统的命令是:

nasm third_stage.asm -f elf -o third_stage.o
gcc -m32 -ffreestanding -c os.c -o os.o
ld -m elf_i386 -o os.bin -Ttext 0x100000 os.o third_stage.o --oformat binary
dd seek=0 if=boot of=os.img
dd seek=1 if=second_stage of=os.img
dd seek=2 if=os.bin of=os.img
dd seek=17 if=/dev/zero of=os.img count=1 bs=512

一开始,我试图在0x8000加载我的操作系统,但执行只是中途停止。我的操作系统正在VirtualBox下进行测试。

阶段 2 中的一个潜在问题是以下代码:

       CopyImage: 
                        mov eax , dword 0x0f
                        mov ebx , dword 0x200
                        mul ebx
                        mov ebx , 4
                        div ebx

DIV EBX 将 EDX:EAX 中的 64 位整数除以 EBX。您没有正确初始化 EDXEDX 是 EDX:EAX 中 64 位数字的高位 32 位,因此您可能希望将 EDX 设置为 0。您可以通过在计算 EAX 的值后添加xor edx, edx指令来修复它。这会将 EDX 置于零。所以代码可能看起来像这样:

       CopyImage: 
                        mov eax , dword 0x0f
                        mov ebx , dword 0x200
                        mul ebx
                        xor edx, edx                   ; zero extend EAX into EDX
                        mov ebx , 4
                        div ebx

您可以使用 2 位向右移动 EAX 而不是 DIV,这与除以 4 相同。像shr eax, 2这样的命令会起作用。但这都是矫枉过正。汇编程序可以在组装时计算此值。上面的所有代码都可以简化为以下指令:

                        mov eax, (0x0f * 0x200)/4

这会将值0x780移动到 EAX 中。


我认为您更大的问题之一是如何将内核链接到os.bin。您可以使用以下方法执行此操作:

ld -m elf_i386 -o os.bin -Ttext 0x100000 os.o third_stage.o --oformat binary

不幸的是,当使用--oformat binary时,_start标签将不会用于确定最终二进制文件中出现的第一个指令。同样,LD 将按照它们出现的顺序处理这些对象。在您的情况下os.o third_stage.o会将代码放在二进制文件中third_stage.o的代码之前os.o。您需要首先显示third_stage.o中的代码,因为这些是您希望在0x100000加载的指令。你应该这样做:

ld -m elf_i386 -o os.bin -Ttext 0x100000 third_stage.o os.o --oformat binary

这个错误似乎是导致你的Guru Meditation错误与VirtualBox的原因。如果没有此修复程序,我可以重现错误,并且通过修复程序,内核确实加载并说这是成功启动的。

相关内容

最新更新