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. laravel整合workerman做聊天室

    测试工具  http://www.blue-zero.com/WebSocket/ 2018年8月6日17:28:24 <?php namespace App\Console\Commands; ...

  2. iostat查看io情况

      查看TPS和吞吐量信息[root@controller ~]#iostat -d -k 1 10Device:         tps    kB_read/s    kB_wrtn/s    k ...

  3. 《图解HTTP》读书笔记(六:HTTP状态码)

    状态码的职责是当客户端向服务器端发送请求时, 描述返回的请求结果. 借助状态码, 用户可以知道服务器端是正常处理了请求, 还是出现了错误. 状态码类别 HTTP状态码由三个十进制数字组成,第一个十进制 ...

  4. 在windows上搭建git server Gitblit

    在Windows上搭建Git Server   第1步:下载Java并安装Java.我这里下载的是jdk1.7.0_79 第2步:配置Java环境变量 右键” 计算机” => ”属性” => ...

  5. mysql储存过程入门学习

    转载至:https://www.yiibai.com/mysql/getting-started-with-mysql-stored-procedures.html 1.mysql储存过程的创建 DE ...

  6. HDD ,SSD和PCIE SSD性能测试

      PCIE SSD   * MB/s = 1,000,000 bytes/s [SATA/600 = 600,000,000 bytes/s] * KB = 1000 bytes, KiB = 10 ...

  7. OpenDialog文件多选

    procedure TForm1.OpenFileListClick(Sender: TObject); var openDialog: TOpenDialog; I: Integer; begin ...

  8. ORA-27300 ORA-27301 ORA-27302 sskgpcreates

    1.环境信息 OS:SUSE 12SP3 DB:12.2.0.1.0 2.数据库启动失败 SQL> startup ORA-27154: post/wait create failed ORA- ...

  9. andorid开发build.gradle 增加几种产品的方法

    因为需要有些ndk的开发,cmakelists里需要定义不同的变量,这个在网上搜索解决方案,不是很容易就直接找到答案. 尝试了不少,最后找到解决方案.升级Gradle3.0,这个文章价值高. 在ras ...

  10. AspnetCore WebApi使用Swagger简单入门

    微软官网入门:https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/web-api-help-pages-using-swagger?view= ...