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,
mov eax,
int 0x80
mov ebx,
mov eax,
int 0x80

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

  接下来使用NASM编译。

  

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

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

  

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

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

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

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

  先来看看c代码:

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

 void myprint(char* msg, int len);

 int choose(int a, int b)
{
if(a >= b){
myprint("the 1st one\n", );
}
else{
myprint("the 2nd one\n", );
} return ;
}

  再来看看汇编代码:

 extern choose

 [section .data]    ; 数据在此

 num1st        dd
num2nd dd [section .text] ; 代码在此 global _start
global myprint _start:
push num2nd
push num1st
call choose
add esp, mov ebx,
mov eax,
int 0x80 ; void myprint(char* msg, int len)
myprint:
mov edx, [esp + ] ; len
mov ecx, [esp + ] ; msg
mov ebx,
mov eax, ; sys_write
int 0x80
ret

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

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

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

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

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

  在Linux终端下查看结果:

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

2. 从Loader到内核

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

  fat12hdr.inc :

 BS_OEMName    DB 'Antz__Os'

 BPB_BytsPerSec    DW
BPB_SecPerClus DB
BPB_RsvdSecCnt DW
BPB_NumFATs DB
BPB_RootEntCnt DW
BPB_TotSec16 DW
BPB_Media DB 0xF0
BPB_FATSz16 DW
BPB_SecPerTrk DW
BPB_NumHeads DW
BPB_HiddSec DD
BPB_TotSec32 DD BS_DrvNum DB
BS_Reserved1 DB
BS_BootSig DB 29h
BS_VolID DD
BS_VolLab DB 'Tinix0.01 '
BS_FileSysType DB 'FAT12 ' FATSz equ
RootDirSectors equ SectorNoOfRootDirectory equ
SectorNoOfFAT1 equ
DeltaSectorNo equ

  boot.asm :

 org  07c00h        

 BaseOfStack        equ    07c00h
BaseOfLoader equ 09000h
OffsetOfLoader equ 0100h jmp short LABEL_START
nop %include "fat12hdr.inc" LABEL_START:
mov ax, cs
mov ds, ax
mov es, ax
mov ss, ax
mov sp, BaseOfStack mov ax, 0600h
mov bx, 0700h
mov cx,
mov dx, 0184fh
int 10h mov dh,
call DispStr xor ah, ah
xor dl, dl
int 13h mov word [wSectorNo], SectorNoOfRootDirectory
LABEL_SEARCH_IN_ROOT_DIR_BEGIN:
cmp word [wRootDirSizeForLoop],
jz LABEL_NO_LOADERBIN
dec word [wRootDirSizeForLoop]
mov ax, BaseOfLoader
mov es, ax
mov bx, OffsetOfLoader
mov ax, [wSectorNo]
mov cl,
call ReadSector mov si, LoaderFileName
mov di, OffsetOfLoader
cld
mov dx, 10h
LABEL_SEARCH_FOR_LOADERBIN:
cmp dx,
jz LABEL_GOTO_NEXT_SECTOR_IN_ROOT_DIR
dec dx
mov cx,
LABEL_CMP_FILENAME:
cmp cx,
jz LABEL_FILENAME_FOUND
dec cx
lodsb
cmp al, byte [es:di]
jz LABEL_GO_ON
jmp LABEL_DIFFERENT LABEL_GO_ON:
inc di
jmp LABEL_CMP_FILENAME LABEL_DIFFERENT:
and di, 0FFE0h
add di, 20h
mov si, LoaderFileName
jmp LABEL_SEARCH_FOR_LOADERBIN LABEL_GOTO_NEXT_SECTOR_IN_ROOT_DIR:
add word [wSectorNo],
jmp LABEL_SEARCH_IN_ROOT_DIR_BEGIN LABEL_NO_LOADERBIN:
mov dh,
call DispStr
%ifdef _BOOT_DEBUG_
mov ax, 4c00h
int 21h
%else
jmp $
%endif LABEL_FILENAME_FOUND:
mov ax, RootDirSectors
and di, 0FFE0h
add di, 01Ah
mov cx, word [es:di]
push cx
add cx, ax
add cx, DeltaSectorNo
mov ax, BaseOfLoader
mov es, ax
mov bx, OffsetOfLoader
mov ax, cx LABEL_GOON_LOADING_FILE:
push ax
push bx
mov ah, 0Eh
mov al, '.'
mov bl, 0Fh
int 10h
pop bx
pop ax mov cl,
call ReadSector
pop ax
call GetFATEntry
cmp ax, 0FFFh
jz LABEL_FILE_LOADED
push ax
mov dx, RootDirSectors
add ax, dx
add ax, DeltaSectorNo
add bx, [BPB_BytsPerSec]
jmp LABEL_GOON_LOADING_FILE
LABEL_FILE_LOADED: mov dh,
call DispStr jmp BaseOfLoader:OffsetOfLoader wRootDirSizeForLoop dw RootDirSectors
wSectorNo dw
bOdd db LoaderFileName db "LOADER BIN", MessageLength equ
BootMessage: db "Booting ";
Message1 db "Ready. ";
Message2 db "No LOADER"; DispStr:
mov ax, MessageLength
mul dh
add ax, BootMessage
mov bp, ax
mov ax, ds
mov es, ax
mov cx, MessageLength
mov ax, 01301h
mov bx, 0007h
mov dl,
int 10h
ret ReadSector:
push bp
mov bp, sp
sub esp, mov byte [bp-], cl
push bx
mov bl, [BPB_SecPerTrk]
div bl
inc ah
mov cl, ah
mov dh, al
shr al,
mov ch, al
and dh,
pop bx mov dl, [BS_DrvNum]
.GoOnReading:
mov ah,
mov al, byte [bp-]
int 13h
jc .GoOnReading add esp,
pop bp ret GetFATEntry:
push es
push bx
push ax
mov ax, BaseOfLoader
sub ax, 0100h
mov es, ax
pop ax
mov byte [bOdd],
mov bx,
mul bx
mov bx,
div bx
cmp dx,
jz LABEL_EVEN
mov byte [bOdd],
LABEL_EVEN:
xor dx, dx
mov bx, [BPB_BytsPerSec]
div bx push dx
mov bx,
add ax, SectorNoOfFAT1
mov cl,
call ReadSector
pop dx
add bx, dx
mov ax, [es:bx]
cmp byte [bOdd],
jnz LABEL_EVEN_2
shr ax,
LABEL_EVEN_2:
and ax, 0FFFh LABEL_GET_FAT_ENRY_OK: pop bx
pop es
ret times -($-$$) db
dw 0xaa55

  loader.asm:

 org  0100h

 BaseOfStack        equ    0100h

 BaseOfKernelFile    equ     08000h
OffsetOfKernelFile equ 0h jmp LABEL_START %include "fat12hdr.inc" LABEL_START:
mov ax, cs
mov ds, ax
mov es, ax
mov ss, ax
mov sp, BaseOfStack mov dh,
call DispStr mov word [wSectorNo], SectorNoOfRootDirectory
xor ah, ah
xor dl, dl
int 13h
LABEL_SEARCH_IN_ROOT_DIR_BEGIN:
cmp word [wRootDirSizeForLoop],
jz LABEL_NO_KERNELBIN
dec word [wRootDirSizeForLoop]
mov ax, BaseOfKernelFile
mov es, ax
mov bx, OffsetOfKernelFile mov ax, [wSectorNo]
mov cl,
call ReadSector mov si, KernelFileName
mov di, OffsetOfKernelFile
cld
mov dx, 10h
LABEL_SEARCH_FOR_KERNELBIN:
cmp dx,
jz LABEL_GOTO_NEXT_SECTOR_IN_ROOT_DIR
dec dx
mov cx,
LABEL_CMP_FILENAME:
cmp cx,
jz LABEL_FILENAME_FOUND
dec cx
lodsb
cmp al, byte [es:di]
jz LABEL_GO_ON
jmp LABEL_DIFFERENT
LABEL_GO_ON:
inc di
jmp LABEL_CMP_FILENAME LABEL_DIFFERENT:
and di, 0FFE0h
add di, 20h
mov si, KernelFileName
jmp LABEL_SEARCH_FOR_KERNELBIN LABEL_GOTO_NEXT_SECTOR_IN_ROOT_DIR:
add word [wSectorNo],
jmp LABEL_SEARCH_IN_ROOT_DIR_BEGIN LABEL_NO_KERNELBIN:
mov dh,
call DispStr
%ifdef _LOADER_DEBUG_
mov ax, 4c00h
int 21h
%else
jmp $
%endif LABEL_FILENAME_FOUND:
mov ax, RootDirSectors
and di, 0FFF0h push eax
mov eax, [es : di + 01Ch]
mov dword [dwKernelSize], eax
pop eax add di, 01Ah
mov cx, word [es:di]
push cx
add cx, ax
add cx, DeltaSectorNo
mov ax, BaseOfKernelFile
mov es, ax
mov bx, OffsetOfKernelFile
mov ax, cx LABEL_GOON_LOADING_FILE:
push ax
push bx
mov ah, 0Eh
mov al, '.'
mov bl, 0Fh
int 10h
pop bx
pop ax mov cl,
call ReadSector
pop ax
call GetFATEntry
cmp ax, 0FFFh
jz LABEL_FILE_LOADED
push ax
mov dx, RootDirSectors
add ax, dx
add ax, DeltaSectorNo
add bx, [BPB_BytsPerSec]
jmp LABEL_GOON_LOADING_FILE
LABEL_FILE_LOADED: call KillMotor mov dh,
call DispStr jmp $ wRootDirSizeForLoop dw RootDirSectors
wSectorNo dw
bOdd db
dwKernelSize dd KernelFileName db "KERNEL BIN",
MessageLength equ
LoadMessage: db "Loading "
Message1 db "Ready. "
Message2 db "No KERNEL" DispStr:
mov ax, MessageLength
mul dh
add ax, LoadMessage
mov bp, ax
mov ax, ds
mov es, ax
mov cx, MessageLength
mov ax, 01301h
mov bx, 0007h
mov dl,
add dh,
int 10h
ret ReadSector: push bp
mov bp, sp
sub esp, mov byte [bp-], cl
push bx
mov bl, [BPB_SecPerTrk]
div bl
inc ah
mov cl, ah
mov dh, al
shr al,
mov ch, al
and dh,
pop bx mov dl, [BS_DrvNum]
.GoOnReading:
mov ah,
mov al, byte [bp-]
int 13h
jc .GoOnReading add esp,
pop bp ret GetFATEntry:
push es
push bx
push ax
mov ax, BaseOfKernelFile
sub ax, 0100h
mov es, ax
pop ax
mov byte [bOdd],
mov bx,
mul bx
mov bx,
div bx
cmp dx,
jz LABEL_EVEN
mov byte [bOdd],
LABEL_EVEN:
xor dx, dx
mov bx, [BPB_BytsPerSec]
div bx push dx
mov bx,
add ax, SectorNoOfFAT1
mov cl,
call ReadSector
pop dx
add bx, dx
mov ax, [es:bx]
cmp byte [bOdd],
jnz LABEL_EVEN_2
shr ax,
LABEL_EVEN_2:
and ax, 0FFFh LABEL_GET_FAT_ENRY_OK: pop bx
pop es
ret KillMotor:
push dx
mov dx, 03F2h
mov al,
out dx, al
pop dx
ret

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

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

  kernel.asm :

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

 [section .text]

 global _start     

 _start:
mov ah, 0Fh ; 0000: 黑底 1111: 白字
mov al, 'K'
mov [gs:(( * + ) * )], ax ; 屏幕第 1 行, 第 39 列。
jmp $

  

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

自制操作系统Antz(7)——实现内核 (上)的更多相关文章

  1. 自制操作系统Antz(10)——实现shell(上)

    我已经规范了系统代码风格,类似于按照linux分包,把各部分功能区分开了 Antz系统更新地址 Linux内核源码分析地址 Github项目地址 在之前的任务中,我们已经通过直接操作显卡驱动完成了简单 ...

  2. 自制操作系统Antz(9)——实现内核 (下) 实现图形化界面

    Antz系统更新地址: https://www.cnblogs.com/LexMoon/category/1262287.html Linux内核源码分析地址:https://www.cnblogs. ...

  3. 自制操作系统Antz(8)——实现内核 (中) 扩展内核

    Antz系统更新地址: https://www.cnblogs.com/LexMoon/category/1262287.html 在前几天的任务中,我们已经简单实现了MBR,直接操作显示器和硬盘操作 ...

  4. 自制操作系统Antz -- 系列文章

    自制操作系统Antz day10——实现shell(上) AntzUhl 2018-10-10 16:25 阅读:192 评论:0   Linux内核源码分析 day01——内存寻址 AntzUhl ...

  5. 自制操作系统Antz(13) 显示图片

    显示图片只是在多媒体课上看着bmp格式图片的突发奇想,然后就实现在了我自己的操作系统 Antz系统更新地址 Linux内核源码分析地址 Github项目地址 效果图: 显示图片的原理 在之前显卡操作时 ...

  6. 自制操作系统Antz(2)——进入保护模式 (上) jmp到保护模式

    Antz系统更新地址: https://www.cnblogs.com/LexMoon/category/1262287.htm Linux内核源码分析地址:https://www.cnblogs.c ...

  7. 自制操作系统Antz(6)——内核初步,引入c语言

    Antz系统更新地址: https://www.cnblogs.com/LexMoon/category/1262287.html Linux内核源码分析地址:https://www.cnblogs. ...

  8. 自制操作系统Antz(4)——进入保护模式 (下) 实现内核并从硬盘载入

    Antz系统更新地址: https://www.cnblogs.com/LexMoon/category/1262287.html Linux内核源码分析地址:https://www.cnblogs. ...

  9. 自制操作系统Antz(1)——Boot Sector

    0.引子 最近在看操作系统底层方面的东西,最开始的为什么是07c00h这个问题就让我对操作系统有了很大的兴趣.所以准备在看书之余顺便写一个操作系统(Anz).至于为什么这个系统会被叫做Antz,可以参 ...

随机推荐

  1. mongodb 性能

    mongo 性能:http://www.mongoing.com/docs/tutorial/optimize-query-performance-with-indexes-and-projectio ...

  2. delphi 自动获取串口

    delphi 自动获取串口   https://blog.csdn.net/Nevermore_anger/article/details/79012875    版权声明:本文为博主原创文章,未经博 ...

  3. ASA failover --AA

    1.A/A Failover  介绍 安全设备可以成对搭配成A/A的FO来提供设备级的冗余和负载分担. 两个设备在互为备份的同时,也能同时转发流量. 使用虚拟子防火墙是必须的,子防火墙被归为两个FO组 ...

  4. fastJson解析报错:com.alibaba.fastjson.JSONException: can't create non-static inner class instance.

    原因: 如果出现类嵌套类的情况,需要将被嵌套的那个类设置为static. 比如: public class AA { // 相关属性 public class BB {//会报错 // 相关属性 } ...

  5. CVU -fixup

    cluvfy(Cluster Verify),简称CVU,是随Oracle集群管理软件一起发布的检查工具. 1.不带fixup grid@WWJD-DB1:/oracle/app/12.2.0/gri ...

  6. 解决git冲突造成的Please move or remove them before you can merge

    git clean -d -fx “” 其中x —–删除忽略文件已经对git来说不识别的文件d —–删除未被添加到git的路径中的文件f —–强制运行如果你确定这货已经没用了,并且git status ...

  7. Adaboost总结

    一.简介 Boosting 是一类算法的总称,这类算法的特点是通过训练若干弱分类器,然后将弱分类器组合成强分类器进行分类.为什么要这样做呢?因为弱分类器训练起来很容易,将弱分类器集成起来,往往可以得到 ...

  8. html-webpack-plugin插件使用时参数配置

    ERROR in multi main Module not found: Error: Cannot resolve 'file' or 'directory' ./public/pages/ind ...

  9. #WEB安全基础 : HTTP协议 | 0x16 HTTPS:证书,证书,全是证书

    现在想做点什么事都需要证书,要不就会让我们回忆起一个典故:滥竽充数 HTTPS使用了公开密钥加密,如何保证公开密钥就是真正的公开密钥呢?攻击者可能会替换公开密钥,这时候就需要验证,所以它采用了数字证书 ...

  10. 第九届蓝桥杯C/C++B组省赛感想

    因为做了近三年的初赛题,都对了5题+,所以这次比赛前信心满满,心里想最少水个省二没问题.可我怎么知道今年的套路居然和以前不一样了!一题深搜都没有,想想一周前做的第七届初赛题,10题有3.4题深搜题. ...