zoukankan      html  css  js  c++  java
  • 自制操作系统Antz(7)——实现内核 (上)

    Antz系统更新地址: https://www.cnblogs.com/LexMoon/category/1262287.html

    Linux内核源码分析地址:https://www.cnblogs.com/LexMoon/category/1267413.html

     

      在前几天的任务中,我们已经简单实现了MBR,直接操作显示器和硬盘操作来加载其他扇区的程序,如今已经可以进入保护模式了,简单引入了C语言,接下来我们编写自己的内核。

    0. 汇编生成ELF

      完成实模式到保护模式跳转的这一任务是由loader进行的,而我们不应该用loader做太多的事,loader只需要完成跳转就好了,剩下的工作交给内核。

      为了加载内核到内存,需要使用ELF格式,如何编译这种格式呢?

      来看看下面这个例子。

    [section .data]
    
    strHello    db    "Hello, Antz !", 0Ah
    STRLEN        equ    $ - strHello
    
    
    [section .text]    
    
    global _start    
    
    _start:
        mov    edx, STRLEN
        mov    ecx, strHello
        mov    ebx, 1
        mov    eax, 4        
        int    0x80        
        mov    ebx, 0
        mov    eax, 1
        int    0x80    

      global _start定义了程序的入口地址,相当于c/c++中main。

      接下来使用NASM编译。

      

      -f elf 指定了输出文件的格式为ELF格式。

      编译完成之后要进行链接,链接指令如下:

      

        (出现警告,在linux无警告,Windows下会有,可以无视)

      -s是strip的简写,可以去掉符号表等内容,对生成的可执行代码进行减肥。

    1. 汇编与C语言共同使用

      我们已经可以生成一个支持载入内存的内核格式文件了,现在我们要学会把汇编程序和c语言程序链接在一起。这是我们编写内核的一大步。

      先来看看c代码:

        其中定义了一个choose函数,声明了一个myprint函数。

     1 void myprint(char* msg, int len);
     2 
     3 int choose(int a, int b)
     4 {
     5     if(a >= b){
     6         myprint("the 1st one
    ", 13);
     7     }
     8     else{
     9         myprint("the 2nd one
    ", 13);
    10     }
    11 
    12     return 0;
    13 }

      再来看看汇编代码:

     1 extern choose
     2 
     3 
     4 [section .data]    ; 数据在此
     5 
     6 num1st        dd    3
     7 num2nd        dd    4
     8 
     9 
    10 [section .text]    ; 代码在此
    11 
    12 global _start    
    13 global myprint    
    14 
    15 _start:
    16     push    num2nd        
    17     push    num1st        
    18     call    choose        
    19     add    esp, 4        
    20 
    21     mov    ebx, 0
    22     mov    eax, 1        
    23     int    0x80    
    24 
    25 ; void myprint(char* msg, int len)
    26 myprint:
    27     mov    edx, [esp + 8]    ; len
    28     mov    ecx, [esp + 4]    ; msg
    29     mov    ebx, 1
    30     mov    eax, 4        ; sys_write
    31     int    0x80    
    32     ret
    33     

      如果你懂汇编,这个代码一定没有如何问题。

      第一行的extern choose就是指c代码中定义的choose函数。

      后面的global导出了函数入口,_start和在c文件中没有定义的myprint函数,myprint在汇编代码中完成了定义。

      _start中调用了choose,choose中又调用了myprint函数。

      这样这两个代码文件内容就很清晰了吧。

      在Linux终端下查看结果:

    1 nasm -f elf foo.asm -o foo.o
    2 gcc -c bar.c -o bar.o
    3 ld -s hello.o bar.o -o foobar
    4 ./foobar

    2. 从Loader到内核

      加载内核到内存和引导扇区的工作很相似,只是处理内核时我们要根据ELF文件结构中的值将内核中相应段放入相应位置。

      fat12hdr.inc :

     1 BS_OEMName    DB 'Antz__Os'
     2 
     3 BPB_BytsPerSec    DW 512    
     4 BPB_SecPerClus    DB 1        
     5 BPB_RsvdSecCnt    DW 1
     6 BPB_NumFATs    DB 2        
     7 BPB_RootEntCnt    DW 224    
     8 BPB_TotSec16    DW 2880        
     9 BPB_Media    DB 0xF0        
    10 BPB_FATSz16    DW 9        
    11 BPB_SecPerTrk    DW 18        
    12 BPB_NumHeads    DW 2        
    13 BPB_HiddSec    DD 0    
    14 BPB_TotSec32    DD 0    
    15 
    16 
    17 BS_DrvNum    DB 0        
    18 BS_Reserved1    DB 0         
    19 BS_BootSig    DB 29h    
    20 BS_VolID    DD 0         
    21 BS_VolLab    DB 'Tinix0.01  '
    22 BS_FileSysType    DB 'FAT12   '    
    23 
    24 FATSz            equ    9     
    25 RootDirSectors        equ    14    
    26 
    27 SectorNoOfRootDirectory    equ    19     
    28 SectorNoOfFAT1        equ    1     
    29 DeltaSectorNo        equ    17     
    30                      

      boot.asm :

      1 org  07c00h        
      2 
      3 BaseOfStack        equ    07c00h 
      4 BaseOfLoader        equ    09000h
      5 OffsetOfLoader        equ    0100h
      6 
      7     jmp short LABEL_START 
      8     nop        
      9     
     10 
     11 %include    "fat12hdr.inc"
     12 
     13 LABEL_START:    
     14     mov    ax, cs
     15     mov    ds, ax
     16     mov    es, ax
     17     mov    ss, ax
     18     mov    sp, BaseOfStack
     19 
     20     
     21     mov    ax, 0600h        
     22     mov    bx, 0700h     
     23     mov    cx, 0         
     24     mov    dx, 0184fh     
     25     int    10h         
     26 
     27     mov    dh, 0         
     28     call    DispStr         
     29     
     30     xor    ah, ah     
     31     xor    dl, dl 
     32     int    13h    
     33 
     34     mov    word [wSectorNo], SectorNoOfRootDirectory
     35 LABEL_SEARCH_IN_ROOT_DIR_BEGIN:
     36     cmp    word [wRootDirSizeForLoop], 0    
     37     jz    LABEL_NO_LOADERBIN        
     38     dec    word [wRootDirSizeForLoop]    
     39     mov    ax, BaseOfLoader
     40     mov    es, ax         
     41     mov    bx, OffsetOfLoader     
     42     mov    ax, [wSectorNo]    
     43     mov    cl, 1
     44     call    ReadSector
     45 
     46     mov    si, LoaderFileName     
     47     mov    di, OffsetOfLoader     
     48     cld
     49     mov    dx, 10h
     50 LABEL_SEARCH_FOR_LOADERBIN:
     51     cmp    dx, 0                                     
     52     jz    LABEL_GOTO_NEXT_SECTOR_IN_ROOT_DIR     
     53     dec    dx                                         
     54     mov    cx, 11
     55 LABEL_CMP_FILENAME:
     56     cmp    cx, 0
     57     jz    LABEL_FILENAME_FOUND 
     58 dec    cx
     59     lodsb             
     60     cmp    al, byte [es:di]
     61     jz    LABEL_GO_ON
     62     jmp    LABEL_DIFFERENT         
     63     
     64 LABEL_GO_ON:
     65     inc    di
     66     jmp    LABEL_CMP_FILENAME     
     67 
     68 LABEL_DIFFERENT:
     69     and    di, 0FFE0h                     
     70     add    di, 20h                         
     71     mov    si, LoaderFileName                     
     72     jmp    LABEL_SEARCH_FOR_LOADERBIN
     73 
     74 LABEL_GOTO_NEXT_SECTOR_IN_ROOT_DIR:
     75     add    word [wSectorNo], 1
     76     jmp    LABEL_SEARCH_IN_ROOT_DIR_BEGIN
     77 
     78 LABEL_NO_LOADERBIN:
     79     mov    dh, 2             
     80     call    DispStr             
     81 %ifdef    _BOOT_DEBUG_
     82     mov    ax, 4c00h      
     83     int    21h         
     84 %else
     85     jmp    $         
     86 %endif
     87 
     88 LABEL_FILENAME_FOUND:         
     89     mov    ax, RootDirSectors
     90     and    di, 0FFE0h     
     91     add    di, 01Ah     
     92     mov    cx, word [es:di]
     93     push    cx             
     94     add    cx, ax
     95     add    cx, DeltaSectorNo     
     96     mov    ax, BaseOfLoader
     97     mov    es, ax             
     98     mov    bx, OffsetOfLoader     
     99     mov    ax, cx
    100 
    101 LABEL_GOON_LOADING_FILE:
    102     push    ax        
    103     push    bx             
    104     mov    ah, 0Eh         
    105     mov    al, '.'            
    106     mov    bl, 0Fh            
    107     int    10h         
    108     pop    bx        
    109     pop    ax             
    110 
    111     mov    cl, 1
    112     call    ReadSector
    113     pop    ax         
    114     call    GetFATEntry
    115     cmp    ax, 0FFFh
    116     jz    LABEL_FILE_LOADED
    117     push    ax         
    118     mov    dx, RootDirSectors
    119     add    ax, dx
    120     add    ax, DeltaSectorNo
    121     add    bx, [BPB_BytsPerSec]
    122     jmp    LABEL_GOON_LOADING_FILE
    123 LABEL_FILE_LOADED:
    124 
    125     mov    dh, 1            
    126     call    DispStr            
    127     
    128     
    129     jmp    BaseOfLoader:OffsetOfLoader    
    130     
    131     
    132 wRootDirSizeForLoop    dw    RootDirSectors     
    133 wSectorNo        dw    0        
    134 bOdd            db    0        
    135 
    136 
    137 LoaderFileName        db    "LOADER  BIN", 0 
    138 
    139 MessageLength        equ    9
    140 BootMessage:        db    "Booting  ";  
    141 Message1        db    "Ready.   "; 
    142 Message2        db    "No LOADER";  
    143 
    144 
    145 DispStr:
    146     mov    ax, MessageLength
    147     mul    dh
    148     add    ax, BootMessage
    149     mov    bp, ax            
    150     mov    ax, ds            
    151     mov    es, ax            
    152     mov    cx, MessageLength     
    153     mov    ax, 01301h         
    154     mov    bx, 0007h         
    155     mov    dl, 0
    156     int    10h             
    157     ret
    158 
    159  
    160 ReadSector:
    161     push    bp
    162     mov    bp, sp
    163     sub    esp, 2             
    164 
    165     mov    byte [bp-2], cl
    166     push    bx         
    167     mov    bl, [BPB_SecPerTrk]    
    168     div    bl             
    169     inc    ah             
    170     mov    cl, ah     
    171     mov    dh, al             
    172     shr    al, 1             
    173     mov    ch, al         
    174     and    dh, 1         
    175     pop    bx         
    176     
    177     mov    dl, [BS_DrvNum]         
    178 .GoOnReading:
    179     mov    ah, 2            
    180     mov    al, byte [bp-2]        
    181     int    13h
    182     jc    .GoOnReading        
    183     
    184     add    esp, 2
    185     pop    bp
    186 
    187     ret
    188 
    189 GetFATEntry:
    190     push    es
    191     push    bx
    192     push    ax
    193     mov    ax, BaseOfLoader     
    194     sub    ax, 0100h         
    195     mov    es, ax             
    196     pop    ax
    197     mov    byte [bOdd], 0
    198     mov    bx, 3
    199     mul    bx         
    200     mov    bx, 2
    201     div    bx             
    202     cmp    dx, 0
    203     jz    LABEL_EVEN
    204     mov    byte [bOdd], 1
    205 LABEL_EVEN:
    206     xor    dx, dx         
    207     mov    bx, [BPB_BytsPerSec]
    208     div    bx            
    209     
    210     push    dx
    211     mov    bx, 0             
    212     add    ax, SectorNoOfFAT1     
    213     mov    cl, 2
    214     call    ReadSector         
    215     pop    dx
    216     add    bx, dx
    217     mov    ax, [es:bx]
    218     cmp    byte [bOdd], 1
    219     jnz    LABEL_EVEN_2
    220     shr    ax, 4
    221 LABEL_EVEN_2:
    222     and    ax, 0FFFh
    223 
    224 LABEL_GET_FAT_ENRY_OK:
    225 
    226     pop    bx
    227     pop    es
    228     ret
    229     
    230 times     510-($-$$)    db    0    
    231 dw     0xaa55                

      loader.asm:

      1 org  0100h
      2  
      3 BaseOfStack        equ    0100h
      4 
      5 BaseOfKernelFile    equ     08000h     
      6 OffsetOfKernelFile    equ         0h    
      7 
      8     jmp    LABEL_START        
      9 
     10 
     11 %include    "fat12hdr.inc"
     12 
     13 
     14 LABEL_START:             
     15     mov    ax, cs
     16     mov    ds, ax
     17     mov    es, ax
     18     mov    ss, ax
     19     mov    sp, BaseOfStack
     20 
     21     mov    dh, 0         
     22     call    DispStr             
     23 
     24     
     25     mov    word [wSectorNo], SectorNoOfRootDirectory    
     26     xor    ah, ah 
     27     xor    dl, dl 
     28     int    13h    
     29 LABEL_SEARCH_IN_ROOT_DIR_BEGIN:
     30     cmp    word [wRootDirSizeForLoop], 0     
     31     jz    LABEL_NO_KERNELBIN         
     32     dec    word [wRootDirSizeForLoop]    
     33     mov    ax, BaseOfKernelFile
     34     mov    es, ax             
     35     mov    bx, OffsetOfKernelFile    
     36     
     37     mov    ax, [wSectorNo]         
     38     mov    cl, 1
     39     call    ReadSector
     40 
     41     mov    si, KernelFileName     
     42     mov    di, OffsetOfKernelFile     
     43     cld
     44     mov    dx, 10h
     45 LABEL_SEARCH_FOR_KERNELBIN:
     46     cmp    dx, 0                     
     47     jz    LABEL_GOTO_NEXT_SECTOR_IN_ROOT_DIR     
     48     dec    dx                     
     49     mov    cx, 11
     50 LABEL_CMP_FILENAME:
     51     cmp    cx, 0             
     52     jz    LABEL_FILENAME_FOUND     
     53     dec    cx             
     54     lodsb 
     55     cmp    al, byte [es:di]     
     56     jz    LABEL_GO_ON
     57     jmp    LABEL_DIFFERENT
     58 LABEL_GO_ON:
     59     inc    di
     60     jmp    LABEL_CMP_FILENAME
     61     
     62 LABEL_DIFFERENT:
     63     and    di, 0FFE0h         
     64     add    di, 20h            
     65     mov    si, KernelFileName
     66     jmp    LABEL_SEARCH_FOR_KERNELBIN
     67     
     68 LABEL_GOTO_NEXT_SECTOR_IN_ROOT_DIR:
     69     add    word [wSectorNo], 1
     70     jmp    LABEL_SEARCH_IN_ROOT_DIR_BEGIN
     71 
     72 LABEL_NO_KERNELBIN:
     73     mov    dh, 2             
     74     call    DispStr         
     75 %ifdef    _LOADER_DEBUG_
     76     mov    ax, 4c00h    
     77     int    21h            
     78 %else
     79     jmp    $         
     80 %endif
     81 
     82 LABEL_FILENAME_FOUND:             
     83     mov    ax, RootDirSectors
     84     and    di, 0FFF0h     
     85 
     86     push    eax
     87     mov    eax, [es : di + 01Ch]         
     88     mov    dword [dwKernelSize], eax 
     89     pop    eax
     90 
     91     add    di, 01Ah     
     92     mov    cx, word [es:di]
     93     push    cx         
     94     add    cx, ax
     95     add    cx, DeltaSectorNo
     96     mov    ax, BaseOfKernelFile
     97     mov    es, ax        
     98     mov    bx, OffsetOfKernelFile    
     99     mov    ax, cx         
    100 
    101 LABEL_GOON_LOADING_FILE:
    102     push    ax         
    103     push    bx             
    104     mov    ah, 0Eh             
    105     mov    al, '.'            
    106     mov    bl, 0Fh             
    107     int    10h         
    108     pop    bx        
    109     pop    ax         
    110 
    111     mov    cl, 1
    112     call    ReadSector
    113     pop    ax         
    114     call    GetFATEntry
    115     cmp    ax, 0FFFh
    116     jz    LABEL_FILE_LOADED
    117     push    ax             
    118     mov    dx, RootDirSectors
    119     add    ax, dx
    120     add    ax, DeltaSectorNo
    121     add    bx, [BPB_BytsPerSec]
    122     jmp    LABEL_GOON_LOADING_FILE
    123 LABEL_FILE_LOADED:
    124 
    125     call    KillMotor         
    126 
    127     mov    dh, 1             
    128     call    DispStr         
    129 
    130     jmp    $
    131 
    132 
    133     
    134 wRootDirSizeForLoop    dw    RootDirSectors
    135 wSectorNo        dw    0         
    136 bOdd            db    0     
    137 dwKernelSize        dd    0     
    138 
    139 
    140 KernelFileName        db    "KERNEL  BIN", 0      
    141 MessageLength        equ    9
    142 LoadMessage:        db    "Loading  "
    143 Message1        db    "Ready.   "
    144 Message2        db    "No KERNEL"
    145 
    146 DispStr:
    147     mov    ax, MessageLength
    148     mul    dh
    149     add    ax, LoadMessage
    150     mov    bp, ax         
    151     mov    ax, ds             
    152     mov    es, ax         
    153     mov    cx, MessageLength     
    154     mov    ax, 01301h         
    155     mov    bx, 0007h     
    156     mov    dl, 0
    157     add    dh, 3         
    158     int    10h         
    159     ret
    160     
    161 ReadSector:
    162  
    163     push    bp
    164     mov    bp, sp
    165     sub    esp, 2         
    166 
    167     mov    byte [bp-2], cl
    168     push    bx             
    169     mov    bl, [BPB_SecPerTrk]     
    170     div    bl             
    171     inc    ah        
    172     mov    cl, ah            
    173     mov    dh, al            
    174     shr    al, 1             
    175     mov    ch, al             
    176     and    dh, 1             
    177     pop    bx
    178     
    179     mov    dl, [BS_DrvNum]         
    180 .GoOnReading:
    181     mov    ah, 2            
    182     mov    al, byte [bp-2]         
    183     int    13h
    184     jc    .GoOnReading        
    185     
    186     add    esp, 2
    187     pop    bp
    188 
    189     ret 
    190     
    191 GetFATEntry:
    192     push    es
    193     push    bx
    194     push    ax
    195     mov    ax, BaseOfKernelFile 
    196     sub    ax, 0100h         
    197     mov    es, ax            
    198     pop    ax
    199     mov    byte [bOdd], 0
    200     mov    bx, 3
    201     mul    bx         
    202     mov    bx, 2
    203     div    bx         
    204     cmp    dx, 0
    205     jz    LABEL_EVEN
    206     mov    byte [bOdd], 1
    207 LABEL_EVEN:
    208     xor    dx, dx             
    209     mov    bx, [BPB_BytsPerSec]
    210     div    bx            
    211     
    212     push    dx
    213     mov    bx, 0         
    214     add    ax, SectorNoOfFAT1     
    215     mov    cl, 2
    216     call    ReadSector         
    217     pop    dx
    218     add    bx, dx
    219     mov    ax, [es:bx]
    220     cmp    byte [bOdd], 1
    221     jnz    LABEL_EVEN_2
    222     shr    ax, 4
    223 LABEL_EVEN_2:
    224     and    ax, 0FFFh
    225 
    226 LABEL_GET_FAT_ENRY_OK:
    227 
    228     pop    bx
    229     pop    es
    230     ret
    231     
    232 KillMotor:
    233     push    dx
    234     mov    dx, 03F2h
    235     mov    al, 0
    236     out    dx, al
    237     pop    dx
    238     ret 

      加载功能已经有了,但是还没有内核给以上程序拿来加载。

      我们来实现一个最简单的内核,以后会基于此扩展。

      kernel.asm :

        此处的K不会打印,因为这里只是假设gs指向了显存。

    1 [section .text]
    2 
    3 global _start     
    4 
    5 _start: 
    6     mov    ah, 0Fh                ; 0000: 黑底    1111: 白字
    7     mov    al, 'K'
    8     mov    [gs:((80 * 1 + 39) * 2)], ax    ; 屏幕第 1 行, 第 39 列。
    9     jmp    $

      

      出现了Ready,说明我们的kernel内核已经加载成功了。

  • 相关阅读:
    魏新 20191017-1 每周例行报告
    魏新 20191010-2 每周例行报告
    魏新 20190919-1 每周例行报告
    魏新 20190919-3 效能分析
    总结
    感谢信
    20191024-1 每周例行报告
    20191017-1 每周例行报告
    第三周作业03
    第三周作业1
  • 原文地址:https://www.cnblogs.com/LexMoon/p/antz07.html
Copyright © 2011-2022 走看看