引导加载程序未加载内核 [英] Bootloader is Not loading the kernel

查看:93
本文介绍了引导加载程序未加载内核的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发我的操作系统.

我在启动操作系统时出错.

错误是:

<块引用>

未找到 KERNEL.BIN!

代码如下:

Boot.asm

<代码>;Aqua_Seven_OS 操作系统引导加载程序;==================================================================位 16jmp 短 bootloader_start ;跳过磁盘描述部分不;在磁盘描述之前填充;------------------------------------------------------------------;磁盘描述表,使其成为有效的软盘;注意:其中一些值在源代码中是硬编码的!;这些值是 IBM 用于 1.44 MB、3.5" 软盘的值OEMLabel db "MIKEBOOT" ;磁盘标签BytesPerSector dw 512;每个扇区的字节数SectorsPerCluster db 1 ;每个集群的扇区ReservedForBoot dw 1 ;引导记录的保留扇区NumberOfFats db 2 ;FAT 的副本数RootDirEntries dw 224 ;根目录中的条目数;(224 * 32 = 7168 = 14 个要读取的扇区)逻辑扇区 dw 2880 ;逻辑扇区数中字节 db 0F0h ;中等描述符字节SectorsPerFat dw 9 ;每个 FAT 的扇区SectorsPerTrack dw 18 ;每个轨道的扇区(36/柱面)侧面 dw 2 ;面数/头数隐藏扇区 dd 0 ;隐藏扇区数大扇区 dd 0 ;LBA 扇区数DriveNo dw 0 ;驱动器编号:0签名 db 41 ;驱动器签名:软盘为 41卷ID dd 00000000h ;卷 ID:任意数字卷标数据库MIKEOS";卷标:任意 11 个字符文件系统数据库FAT12";文件系统类型:不要改变!;------------------------------------------------------------------;主引导程序代码bootloader_start:移动斧头,07C0h;在缓冲区上方设置 4K 的堆栈空间添加斧头,544;8k 缓冲区 = 512 段 + 32 段(加载器)cli;更改堆栈时禁用中断mov ss, 斧头mov sp, 4096斯蒂;恢复中断移动斧头,07C0h;将数据段设置为我们加载的位置mov ds, ax;注意:一些早期的 BIOS 被报告不正确设置 DLcmp dl, 0我没有_改变mov [bootdev], dl ;保存启动设备号动啊, 8 ;获取驱动参数13 小时jc fatal_disk_error和 cx, 3Fh ;最大扇区数mov [SectorsPerTrack], cx ;扇区编号从 1 开始movzx dx, dh ;最大头数添加 dx, 1 ;头数从 0 开始 - 总数加 1mov [边], dx没有变化:移动 eax, 0 ;一些较旧的 BIOS 需要;首先,我们需要从磁盘加载根目录.技术细节:;根的开始 = ReservedForBoot + NumberOfFats * SectorsPerFat = 逻辑 19;根数 = RootDirEntries * 32 字节/条目/512 字节/扇区 = 14;用户数据的开始=(根的开始)+(根的数量)=逻辑33floppy_ok: ;准备读取第一个数据块移动斧头,19;根目录从逻辑扇区 19 开始呼叫 l2htsmov si, 缓冲区;设置 ES:BX 指向我们的缓冲区(见代码结尾)mov bx, ds移动 es, bxmov bx, si动啊, 2 ;int 13h 的参数:读取软盘扇区运动, 14 ;并阅读其中的 14 个推送;准备进入循环read_root_dir:流行音乐;如果寄存器被 int 13h 改变普萨stc ;一些 BIOS 没有正确设置错误整数 13 小时;使用 BIOS 读取扇区jnc search_dir ;如果阅读正常,请跳过调用 reset_floppy ;否则,重置软盘控制器并重试jnc read_root_dir ;软盘重置好吗?jmp重启;如果不是,致命的双重错误搜索目录:波帕mov ax, ds ;根目录现在在 [缓冲区]移动,斧头;将 DI 设置为此信息mov di, 缓冲区mov cx, word [RootDirEntries] ;搜索所有 (224) 条目移动斧头, 0 ;在偏移量 0 处搜索next_root_entry:xchg cx, dx ;我们在内循环中使用CX...mov si, kern_filename ;开始搜索内核文件名mov cx, 11代表 cmpsbje found_file_to_load ;指针 DI 将位于偏移量 11添加斧头,32;将搜索的条目按 1(每个条目 32 字节)mov di, 缓冲区;指向下一个条目添加迪,斧头xchg dx, cx ;取回原始 CX循环 next_root_entrymov si, file_not_found ;如果未找到内核,请退出调用 print_stringjmp重启found_file_to_load: ;获取簇并将 FAT 加载到 RAM 中mov ax, word [es:di+0Fh] ;偏移量 11 + 15 = 26,包含第一个簇mov word [簇], ax移动斧头, 1 ;扇区 1 = 第一个 FAT 的第一个扇区呼叫 l2htsmov di, 缓冲区;ES:BX 指向我们的缓冲区mov bx, di动啊, 2 ;int 13h 参数:读取(FAT)扇区运动, 9 ;第一个 FAT 的所有 9 个扇区推送;准备进入循环读胖:流行音乐;如果寄存器被 int 13h 改变普萨stc整数 13 小时;使用 BIOS 读取扇区jnc read_fat_ok ;如果阅读正常,请跳过调用 reset_floppy ;否则,重置软盘控制器并重试jnc read_fat ;软盘重置好吗?;**********************************************************************致命磁盘错误:;**********************************************************************mov si, disk_error ;如果没有,打印错误信息并重启调用 print_stringjmp重启;致命的双重错误read_fat_ok:波帕移动斧头,2000 小时;我们将加载内核的段移动,斧头移动 bx, 0动啊, 2 ;int 13h 软盘读取参数移动, 1推斧头;保存以防我们(或 int 调用)丢失它;现在我们必须从磁盘加载 FAT.以下是我们如何找出它的起点:;FAT 簇 0 = 媒体描述符 = 0F0h;FAT 簇 1 = 填充簇 = 0FFh;集群开始 = ((集群编号) - 2) * SectorsPerCluster + (用户开始);=(簇数)+ 31load_file_sector:mov ax, word [cluster] ;将扇区转换为逻辑添加斧头,31调用 l2hts ;为 int 13h 设置适当的参数移动斧头,2000 小时;将缓冲区设置为我们已经阅读过的内容移动,斧头mov bx, word [指针]流行斧头;保存以防我们(或 int 调用)丢失它推斧stc13 小时jnc calculate_next_cluster ;如果没有错误...调用 reset_floppy ;否则,重置软盘并重试jmp load_file_sector;在 FAT 中,簇值以 12 位存储,因此我们必须;做一些数学运算来确定我们是否正在处理一个字节;和下一个字节的 4 位——或一个字节的最后 4 位;然后是随后的字节!calculate_next_cluster:mov ax, [集群]移动 dx, 0mov bx, 3多路复用mov bx, 2div bx ;DX = [集群] mod 2mov si, 缓冲区添加 si, ax ;AX = FAT 中 12 位条目的字mov ax, word [ds:si]或 dx, dx ;如果 DX = 0 [cluster] 是偶数;如果 DX = 1 那么它是奇数jz甚至;如果 [cluster] 是偶数,则删除单词的最后 4 位;与下一个集群;如果奇数,丢弃前 4 位奇怪的:shr 斧头, 4 ;移出前 4 位(它们属于另一个条目)jmp 短 next_cluster_cont甚至:和斧头,0FFFh;屏蔽最后 4 位next_cluster_cont:mov word [簇], ax ;店铺集群cmp ax, 0FF8h ;FF8h = FAT12 中的文件结束标记宰端添加单词 [指针], 512 ;增加缓冲区指针1扇区长度jmp load_file_sector结尾:                    ;我们有要加载的文件!流行斧头;清理堆栈(AX 之前被压入)mov dl, 字节 [bootdev] ;为内核提供引导设备信息jmp 2000h:0000h ;跳转到加载内核的入口点!;------------------------------------------------------------------;自举程序子程序重启:移动斧头,0整数 16 小时;等待击键移动斧头,0整数 19 小时;重新启动系统打印字符串:;将 SI 中的字符串输出到屏幕普萨移动啊, 0Eh ;int 10h 电传功能.重复:lodsb ;从字符串中获取字符cmp al, 0je .done ;如果 char 为零,则字符串结束整数 10 小时;否则打印jmp 短.repeat.完毕:波帕回复reset_floppy: ;IN:[bootdev] = 启动设备;OUT:进位设置错误推斧推dx移动斧头,0mov dl, 字节 [bootdev]stc13 小时流行音乐流行斧回复l2hts: ;计算 int 13h 的磁头、磁道和扇区设置;IN:AX 中的逻辑扇区,OUT:int 13h 的正确寄存器推bx推斧mov bx, ax ;保存逻辑扇区移动 dx, 0 ;首先是部门div 字 [SectorsPerTrack]添加 dl, 01h ;物理扇区从 1 开始mov cl, dl ;扇区属于 CL for int 13hmov ax, bx移动 dx, 0 ;现在计算头部div 字 [SectorsPerTrack]移动 dx, 0div 字 [双方]mov dh, dl ;头/侧mov ch, al ;追踪流行斧流行音乐mov dl, 字节 [bootdev] ;设置正确的设备回复;------------------------------------------------------------------;字符串和变量kern_filename 数据库内核库";内核文件名disk_error db "软盘错误!按任意键...", 0file_not_found db "未找到 KERNEL.BIN!", 0引导开发数据库 0 ;引导设备号集群 dw 0 ;我们要加载的文件簇指针 dw 0 ;指向缓冲区的指针,用于加载内核;------------------------------------------------------------------;引导扇区结束和缓冲区开始次 510-($-$$) db 0 ;用零填充引导扇区的剩余部分dw 0AA55h ;引导签名(请勿更改!)缓冲:             ;磁盘缓冲区开始(此后 8k,堆栈开始);==================================================================

我在互联网上找到了启动代码.

内核.asm

<预><代码>[位 16]移动斧头, 0 ;设置细分mov ds, ax移动,斧头mov ss, ax ;设置栈mov sp, 0x7C00 ;堆栈从 0x7C00 向下增长动啊,9mov bl, 9mov cx, 1110 小时mov DX, boota21小时mov si, boota ;打印启动信息调用 print_string主循环:mov si, 提示调用 print_string ;提示数据库>"mov di, 缓冲区调用 get_stringmov si, 缓冲区cmp 字节 [si], 0 ;空行?主循环;是的,忽略它mov si, 缓冲区mov di, cmd_reb ;重启"命令调用 strcmpjc .rebootmov si, 缓冲区mov di, cmd_shut ;关机"命令调用 strcmp关闭mov si,badcommand调用 print_string ;如果没有这样的命令怎么办?jmp主循环;jmp主循环:-).重启: ;重启功能数据库 0x0eadw 0x0000dw 0xffff.shut: ;关机功能运动, 02h移动啊,00h10 小时mov si, 关闭调用 print_string移动斧头,0x1000mov ax, ssmov sp, 0xf000移动斧头,0x5307移动 bx, 0x0001mov cx, 0x0003整数 0x15;------变量------------Shutm db 'MCOS 成功关闭.现在您可以关闭计算机.', 0x0d, 0x0a, 0boota db '正在启动 MotoSoft COS 1...', 0x0d, 0x0a, 0缓冲时间 64 db 0提示 db '>', 0badcommand db '输入了错误的命令.', 0x0D, 0x0A, 0cmd_reb 数据库重启",0;================;电话从这里开始;================打印字符串:lodsb ;从 SI 中获取一个字节或 al, al ;逻辑或 AL 本身jz.完成;如果结果为零,请出去移动啊,0x0E整数 0x10 ;否则,打印出字符!jmp 打印字符串.完毕:回复获取字符串:异或 cl, cl.环形:移动啊,0整数 0x16 ;等待按键cmp al, 0x08 ;按退格键?je .backspace ;是的,处理它cmp al, 0x0D ;输入按下?je .done ;是的,我们完成了cmp cl, 0x3F ;输入了 63 个字符?je .loop ;是的,只让退格并输入移动啊,0x0E整数 0x10 ;打印字符stosb ;将字符放入缓冲区包括循环.退格:cmp cl, 0 ;字符串的开头?je .loop ;是的,忽略关键德迪移动字节 [di], 0 ;删除字符dec ;递减计数器移动啊,0x0E移动,0x08整数 10 小时;屏幕上的退格移动, ' '整数 10 小时;出空白字符移动,0x08整数 10 小时;再次退格jmp .loop ;转到主循环.完毕:运动, 0 ;空终止符stosb移动啊,0x0E移动,0x0D整数 0x10移动, 0x0A整数 0x10 ;新队回复力量:.环形:mov al, [si] ;从 SI 中获取一个字节mov bl, [di] ;从 DI 中获取一个字节cmp al, bl ;他们平等吗?jne .notequal ;不,我们已经完成了.cmp al, 0 ;两个字节(它们之前相等)是否为空?je .done ;是的,我们完成了.公司 迪;增加DI公司 ;增加SIjmp .loop ;环形!.notequal:胆固醇;不相等,清除进位标志回复.完毕:stc ;相等,设置进位标志回复cmd_shut db 'shutdwon', 0```

我从互联网上获得了所有这些代码,我正在制作我的 HOBBY OS.

和编译代码:-

nasm -f bin -o boot.bin boot.asmnasm -f bin -o kernel.bin kernel.asmdd if=/dev/zero of=disk.img bs=512 count=2880dd if=boot.bin of=disk.img bs=512 conv=notruncdd if=kernel.bin of=disk.img bs=512 seek=1 conv=notrunc

当我启动我的操作系统时,它显示

<块引用>

未找到 KERNEL.BIN!

错误图片:

解决方案

如果您打算使用 MIKEOS 引导加载程序,那么您需要创建一个 FAT12 格式的 1.44MiB 软盘映像以与卷引导记录 (VBR) 兼容boot.asm.然后您需要将您的 KERNEL.BIN 复制到该图像中.

使用 mtools 包,这个过程非常简单.mtools


内核问题

kernel.asm 中的主要问题是:

  • DS 段寄存器设置不正确.MIKEOS 在内存中的 0x2000:0x0000 (segment:offset) 加载您的内核.您需要一个与偏移部分匹配的 ORG.您需要加载带有段部分 (0x2000) 的 DS(如果需要,还可以加载 ES).

  • 在使用像 LODS/STOS/SCAS 这样的字符串指令之前,您要确保方向标志 (DF) 设置为您期望的方式.使用 CLD 会将 DF=0 设置为向前移动,这是您的代码所期望的.

  • 您似乎还调用了 int 21h 进行打印.代码似乎是从 DOS 程序中遗留下来的,您打算将其删除.

  • 您在 cmd_shut 字符串中拼错了 shutdown.您错误地将其拼写为 shutdwon.

  • 不清楚你想用这段代码做什么:

     mov ah, 9 ;不清楚你在这里想做什么?mov bl, 9mov cx, 11整数 10 小时;???

您不妨考虑删除它.

可以将代码的开头修改为:

[位 16]组织 0x0000移动斧头,0x2000;设置段以匹配 CS=0x2000mov ds, ax移动,斧头异或斧头,斧头mov ss, ax ;将堆栈段设置为 0x0000mov sp, 0x7C00 ;堆栈从 0x0000:0x7C00 向下增长CL ;清除方向标志(DF=0 是向前的弦移动)动啊, 9 ;不清楚你在这里想做什么?mov bl, 9mov cx, 11整数 10 小时;???mov si, boota ;打印启动信息调用 print_string[剪辑]

您拼写错误 shutdown,因此它不会被正确识别为命令.应该是:

cmd_shut db 'shutdown', 0

通过这些更改,代码在运行时如下所示:

I am developing my Operating System.

I got error on booting my OS.

The error was:

KERNEL.BIN not found!

Here are the Codes:

Boot.asm

; The Aqua_Seven_OS Operating System bootloader
; ==================================================================


    BITS 16

    jmp short bootloader_start  ; Jump past disk description section
    nop             ; Pad out before disk description


; ------------------------------------------------------------------
; Disk description table, to make it a valid floppy
; Note: some of these values are hard-coded in the source!
; Values are those used by IBM for 1.44 MB, 3.5" diskette

OEMLabel        db "MIKEBOOT"   ; Disk label
BytesPerSector      dw 512      ; Bytes per sector
SectorsPerCluster   db 1        ; Sectors per cluster
ReservedForBoot     dw 1        ; Reserved sectors for boot record
NumberOfFats        db 2        ; Number of copies of the FAT
RootDirEntries      dw 224      ; Number of entries in root dir
                    ; (224 * 32 = 7168 = 14 sectors to read)
LogicalSectors      dw 2880     ; Number of logical sectors
MediumByte      db 0F0h     ; Medium descriptor byte
SectorsPerFat       dw 9        ; Sectors per FAT
SectorsPerTrack     dw 18       ; Sectors per track (36/cylinder)
Sides           dw 2        ; Number of sides/heads
HiddenSectors       dd 0        ; Number of hidden sectors
LargeSectors        dd 0        ; Number of LBA sectors
DriveNo         dw 0        ; Drive No: 0
Signature       db 41       ; Drive signature: 41 for floppy
VolumeID        dd 00000000h    ; Volume ID: any number
VolumeLabel     db "MIKEOS     "; Volume Label: any 11 chars
FileSystem      db "FAT12   "   ; File system type: don't change!


; ------------------------------------------------------------------
; Main bootloader code

bootloader_start:
    mov ax, 07C0h           ; Set up 4K of stack space above buffer
    add ax, 544         ; 8k buffer = 512 paragraphs + 32 paragraphs (loader)
    cli             ; Disable interrupts while changing stack
    mov ss, ax
    mov sp, 4096
    sti             ; Restore interrupts

    mov ax, 07C0h           ; Set data segment to where we're loaded
    mov ds, ax

    ; NOTE: A few early BIOSes are reported to improperly set DL

    cmp dl, 0
    je no_change
    mov [bootdev], dl       ; Save boot device number
    mov ah, 8           ; Get drive parameters
    int 13h
    jc fatal_disk_error
    and cx, 3Fh         ; Maximum sector number
    mov [SectorsPerTrack], cx   ; Sector numbers start at 1
    movzx dx, dh            ; Maximum head number
    add dx, 1           ; Head numbers start at 0 - add 1 for total
    mov [Sides], dx

no_change:
    mov eax, 0          ; Needed for some older BIOSes


; First, we need to load the root directory from the disk. Technical details:
; Start of root = ReservedForBoot + NumberOfFats * SectorsPerFat = logical 19
; Number of root = RootDirEntries * 32 bytes/entry / 512 bytes/sector = 14
; Start of user data = (start of root) + (number of root) = logical 33

floppy_ok:              ; Ready to read first block of data
    mov ax, 19          ; Root dir starts at logical sector 19
    call l2hts

    mov si, buffer          ; Set ES:BX to point to our buffer (see end of code)
    mov bx, ds
    mov es, bx
    mov bx, si

    mov ah, 2           ; Params for int 13h: read floppy sectors
    mov al, 14          ; And read 14 of them

    pusha               ; Prepare to enter loop


read_root_dir:
    popa                ; In case registers are altered by int 13h
    pusha

    stc             ; A few BIOSes do not set properly on error
    int 13h             ; Read sectors using BIOS

    jnc search_dir          ; If read went OK, skip ahead
    call reset_floppy       ; Otherwise, reset floppy controller and try again
    jnc read_root_dir       ; Floppy reset OK?

    jmp reboot          ; If not, fatal double error


search_dir:
    popa

    mov ax, ds          ; Root dir is now in [buffer]
    mov es, ax          ; Set DI to this info
    mov di, buffer

    mov cx, word [RootDirEntries]   ; Search all (224) entries
    mov ax, 0           ; Searching at offset 0


next_root_entry:
    xchg cx, dx         ; We use CX in the inner loop...

    mov si, kern_filename       ; Start searching for kernel filename
    mov cx, 11
    rep cmpsb
    je found_file_to_load       ; Pointer DI will be at offset 11

    add ax, 32          ; Bump searched entries by 1 (32 bytes per entry)

    mov di, buffer          ; Point to next entry
    add di, ax

    xchg dx, cx         ; Get the original CX back
    loop next_root_entry

    mov si, file_not_found      ; If kernel is not found, bail out
    call print_string
    jmp reboot


found_file_to_load:         ; Fetch cluster and load FAT into RAM
    mov ax, word [es:di+0Fh]    ; Offset 11 + 15 = 26, contains 1st cluster
    mov word [cluster], ax

    mov ax, 1           ; Sector 1 = first sector of first FAT
    call l2hts

    mov di, buffer          ; ES:BX points to our buffer
    mov bx, di

    mov ah, 2           ; int 13h params: read (FAT) sectors
    mov al, 9           ; All 9 sectors of 1st FAT

    pusha               ; Prepare to enter loop


read_fat:
    popa                ; In case registers are altered by int 13h
    pusha

    stc
    int 13h             ; Read sectors using the BIOS

    jnc read_fat_ok         ; If read went OK, skip ahead
    call reset_floppy       ; Otherwise, reset floppy controller and try again
    jnc read_fat            ; Floppy reset OK?

; ******************************************************************
fatal_disk_error:
; ******************************************************************
    mov si, disk_error      ; If not, print error message and reboot
    call print_string
    jmp reboot          ; Fatal double error


read_fat_ok:
    popa

    mov ax, 2000h           ; Segment where we'll load the kernel
    mov es, ax
    mov bx, 0

    mov ah, 2           ; int 13h floppy read params
    mov al, 1

    push ax             ; Save in case we (or int calls) lose it


; Now we must load the FAT from the disk. Here's how we find out where it starts:
; FAT cluster 0 = media descriptor = 0F0h
; FAT cluster 1 = filler cluster = 0FFh
; Cluster start = ((cluster number) - 2) * SectorsPerCluster + (start of user)
;               = (cluster number) + 31

load_file_sector:
    mov ax, word [cluster]      ; Convert sector to logical
    add ax, 31

    call l2hts          ; Make appropriate params for int 13h

    mov ax, 2000h           ; Set buffer past what we've already read
    mov es, ax
    mov bx, word [pointer]

    pop ax              ; Save in case we (or int calls) lose it
    push ax

    stc
    int 13h

    jnc calculate_next_cluster  ; If there's no error...

    call reset_floppy       ; Otherwise, reset floppy and retry
    jmp load_file_sector


    ; In the FAT, cluster values are stored in 12 bits, so we have to
    ; do a bit of maths to work out whether we're dealing with a byte
    ; and 4 bits of the next byte -- or the last 4 bits of one byte
    ; and then the subsequent byte!

calculate_next_cluster:
    mov ax, [cluster]
    mov dx, 0
    mov bx, 3
    mul bx
    mov bx, 2
    div bx              ; DX = [cluster] mod 2
    mov si, buffer
    add si, ax          ; AX = word in FAT for the 12 bit entry
    mov ax, word [ds:si]

    or dx, dx           ; If DX = 0 [cluster] is even; if DX = 1 then it's odd

    jz even             ; If [cluster] is even, drop last 4 bits of word
                    ; with next cluster; if odd, drop first 4 bits

odd:
    shr ax, 4           ; Shift out first 4 bits (they belong to another entry)
    jmp short next_cluster_cont


even:
    and ax, 0FFFh           ; Mask out final 4 bits


next_cluster_cont:
    mov word [cluster], ax      ; Store cluster

    cmp ax, 0FF8h           ; FF8h = end of file marker in FAT12
    jae end

    add word [pointer], 512     ; Increase buffer pointer 1 sector length
    jmp load_file_sector


end:                    ; We've got the file to load!
    pop ax              ; Clean up the stack (AX was pushed earlier)
    mov dl, byte [bootdev]      ; Provide kernel with boot device info

    jmp 2000h:0000h         ; Jump to entry point of loaded kernel!


; ------------------------------------------------------------------
; BOOTLOADER SUBROUTINES

reboot:
    mov ax, 0
    int 16h             ; Wait for keystroke
    mov ax, 0
    int 19h             ; Reboot the system


print_string:               ; Output string in SI to screen
    pusha

    mov ah, 0Eh         ; int 10h teletype function

.repeat:
    lodsb               ; Get char from string
    cmp al, 0
    je .done            ; If char is zero, end of string
    int 10h             ; Otherwise, print it
    jmp short .repeat

.done:
    popa
    ret


reset_floppy:       ; IN: [bootdev] = boot device; OUT: carry set on error
    push ax
    push dx
    mov ax, 0
    mov dl, byte [bootdev]
    stc
    int 13h
    pop dx
    pop ax
    ret


l2hts:          ; Calculate head, track and sector settings for int 13h
            ; IN: logical sector in AX, OUT: correct registers for int 13h
    push bx
    push ax

    mov bx, ax          ; Save logical sector

    mov dx, 0           ; First the sector
    div word [SectorsPerTrack]
    add dl, 01h         ; Physical sectors start at 1
    mov cl, dl          ; Sectors belong in CL for int 13h
    mov ax, bx

    mov dx, 0           ; Now calculate the head
    div word [SectorsPerTrack]
    mov dx, 0
    div word [Sides]
    mov dh, dl          ; Head/side
    mov ch, al          ; Track

    pop ax
    pop bx

    mov dl, byte [bootdev]      ; Set correct device

    ret


; ------------------------------------------------------------------
; STRINGS AND VARIABLES

    kern_filename   db "KERNEL  BIN"    ; kernel filename

    disk_error  db "Floppy error! Press any key...", 0
    file_not_found  db "KERNEL.BIN not found!", 0

    bootdev     db 0    ; Boot device number
    cluster     dw 0    ; Cluster of the file we want to load
    pointer     dw 0    ; Pointer into Buffer, for loading kernel


; ------------------------------------------------------------------
; END OF BOOT SECTOR AND BUFFER START

    times 510-($-$$) db 0   ; Pad remainder of boot sector with zeros
    dw 0AA55h       ; Boot signature (DO NOT CHANGE!)


buffer:             ; Disk buffer begins (8k after this, stack starts)


; ==================================================================

I found the boot code on internet.

Kernel.asm


[bits 16]



   mov ax, 0  ; set up segments
   mov ds, ax
   mov es, ax
   mov ss, ax     ; setup stack
   mov sp, 0x7C00 ; stack grows downwards from 0x7C00

   mov ah, 9
   mov bl, 9
   mov cx, 11 
   int 10h
   mov DX, boota
   int 21H

   mov si, boota         ;Print boot message
   call print_string

 mainloop:
   mov si, prompt
   call print_string          ; prompt db ">"

   mov di, buffer
   call get_string

   mov si, buffer
   cmp byte [si], 0  ; blank line?
   je mainloop       ; yes, ignore it

   mov si, buffer
   mov di, cmd_reb  ; "reboot" command
   call strcmp
   jc .reboot

   mov si, buffer
   mov di, cmd_shut  ; "shutdown" command
   call strcmp
   jc .shut

   mov si,badcommand
   call print_string     ; What if there is no such command?
   jmp mainloop        ; jmp mainloop :-)

 .reboot:                           ; reboot function
   db 0x0ea 
   dw 0x0000 
   dw 0xffff

 .shut:                                   ;shutdown function

   mov al, 02h      
   mov ah, 00h      
   int 10h

   mov si, shutm
   call print_string

   mov ax, 0x1000
   mov ax, ss
   mov sp, 0xf000
   mov ax, 0x5307
   mov bx, 0x0001
   mov cx, 0x0003
   int 0x15

   ; ------Variables-------------
 shutm  db 'The MCOS shutdowned sucessfully. Now you may power off the computer.', 0x0d, 0x0a, 0
 boota db 'Booting MotoSoft COS 1...', 0x0d, 0x0a, 0
 buffer times 64 db 0
 prompt db '>', 0
 badcommand db 'Bad command entered.', 0x0D, 0x0A, 0 
 cmd_reb db 'reboot', 0


 ; ================
 ; calls start here
 ; ================

 print_string:
   lodsb        ; grab a byte from SI

   or al, al  ; logical or AL by itself
   jz .done   ; if the result is zero, get out

   mov ah, 0x0E
   int 0x10      ; otherwise, print out the character!

   jmp print_string

 .done:
   ret

 get_string:
   xor cl, cl

 .loop:
   mov ah, 0
   int 0x16   ; wait for keypress

   cmp al, 0x08    ; backspace pressed?
   je .backspace   ; yes, handle it

   cmp al, 0x0D  ; enter pressed?
   je .done      ; yes, we're done

   cmp cl, 0x3F  ; 63 chars inputted?
   je .loop      ; yes, only let in backspace and enter
   mov ah, 0x0E
   int 0x10      ; print out character

   stosb  ; put character in buffer
   inc cl
   jmp .loop

 .backspace:
   cmp cl, 0    ; beginning of string?
   je .loop ; yes, ignore the key

   dec di
   mov byte [di], 0 ; delete character
   dec cl       ; decrement counter as well

   mov ah, 0x0E
   mov al, 0x08
   int 10h      ; backspace on the screen

   mov al, ' '
   int 10h      ; blank character out

   mov al, 0x08
   int 10h      ; backspace again

   jmp .loop    ; go to the main loop

 .done:
   mov al, 0    ; null terminator
   stosb

   mov ah, 0x0E
   mov al, 0x0D
   int 0x10
   mov al, 0x0A
   int 0x10     ; newline

   ret

 strcmp:
 .loop:
   mov al, [si]   ; grab a byte from SI
   mov bl, [di]   ; grab a byte from DI
   cmp al, bl     ; are they equal?
   jne .notequal  ; nope, we're done.

   cmp al, 0  ; are both bytes (they were equal before) null?
   je .done   ; yes, we're done.

   inc di     ; increment DI
   inc si     ; increment SI
   jmp .loop  ; loop!

 .notequal:
   clc  ; not equal, clear the carry flag
   ret

 .done:     
   stc  ; equal, set the carry flag
   ret


cmd_shut db 'shutdwon', 0```

I got all these codes from internet and i am making my HOBBY OS.

And the compiling Codes:-

nasm -f bin -o boot.bin boot.asm
nasm -f bin -o kernel.bin kernel.asm
dd if=/dev/zero of=disk.img bs=512 count=2880
dd if=boot.bin of=disk.img bs=512 conv=notrunc
dd if=kernel.bin of=disk.img bs=512 seek=1 conv=notrunc

When I boot my OS, it shows

KERNEL.BIN not found!

Image of error:

解决方案

If you intend on using the MIKEOS bootloader then you need to create a FAT12 formatted 1.44MiB floppy disk image to be compatible with the volume boot record (VBR) in boot.asm. You then need to copy your KERNEL.BIN into that image.

This process is quite simple with the mtools package. mtools has online documentation. This answer isn't a complete guide to using mtools but enough to do what you need to boot. If you are using Debian or a Debian based distro like Ubuntu you can install the mtools package as root user with:

apt-get install mtools

The mtools package comes with a mformat program that can create 1.44MiB disk image; format it as FAT12; and have it automatically place your boot.bin program in the first sector. The command would be:

mformat -f1440 -B boot.bin -C -i disk.img

This should create a 1.44MiB disk image file called disk.img. To copy a file like KERNEL.BIN into disk.img you'd use the command:

mcopy -D o -i disk.img KERNEL.BIN ::/

The -D o option forces mcopy to overwrite a file if it exists. -i disk.img specifies the name of the disk image file KERNEL.BIN is the file we want to copy into the image (source file(s)). :: is a special device name to refer to the disk image itself. The / is the root directory. Together ::/ at the end of the command is the target location to put the file - in the root directory of the disk image.

You can use the mdir command to get a file listing of the root directory.

mdir -i disk.img ::/

This works similar to dir / in DOS. The output would look something like:

 Volume in drive : has no label
 Volume Serial Number is 6F67-C526
Directory for ::/

KERNEL   BIN        74 2019-12-20  13:25
        1 file                   74 bytes
                          1 457 152 bytes free

I have created a kernel.asm that replaces yours as yours has problems that are beyond the scope of your question. I provide this one as a sample that should work:

ORG 0x0000

start:
    mov ax, 0x2000             ; Mike OS'es bootloader loads us at 0x2000:0x0000
    mov ds, ax                 ; Set DS = ES = 0x2000
    mov es, ax

    ; Stack just below 0x2000:0x0000 starting at 0x1000:0x0000.
    ; First push will set SS:SP to 0x1000:0xfffe because SP will wrap.
    mov ax, 0x1000
    mov ss, ax
    xor sp, sp

    cld                        ; Clear Direction Flag (DF=0 is forward string movement)

    mov si, testCodeStr
    call print_string

    cli
.end_loop:
    hlt
    jmp .end_loop

testCodeStr: db 0x0d, 0x0a, "KERNEL.BIN loaded and running...", 0

; Function: print_string
;           Display a string to the console on display page 0
;
; Inputs:   SI = Offset of address to print
; Clobbers: AX, BX, SI

print_string:
    mov ah, 0x0e                ; BIOS tty Print
    xor bx, bx                  ; Set display page to 0 (BL)
    jmp .getch
.repeat:
    int 0x10                    ; print character
.getch:
    lodsb                       ; Get character from string
    test al,al                  ; Have we reached end of string?
    jnz .repeat                 ;     if not process next character
.end:
    ret

This code is intended to work with MIKEOS's bootloader that loads and runs the kernel from 0x2000:0x0000 in memory. I use an ORG 0x0000 at the top and set DS and ES to 0x2000 to correspond to where we are loaded in memory. I also set SS:SP to an initial value of 0x1000:00000. The first time you push a 16-bit value on the stack SS:SP will be 0x1000:0xFFFE (physical address 0x1FFFE) just below the load address of the kernel at 0x2000:0x0000 (physical address 0x20000).

When assembled and the disk image built and run in QEMU with the commands:

nasm -f bin boot.asm -o boot.bin
nasm -f bin kernel.asm -o KERNEL.BIN
mformat -f1440 -B boot.bin -C -i disk.img
mcopy -D o -i disk.img KERNEL.BIN ::/

qemu-system-i386 -fda disk.img

The output should look similar to:


Kernel problems

The main problems in your kernel.asm are:

  • Incorrectly setting the DS segment register. MIKEOS loaded your kernel at 0x2000:0x0000 (segment:offset) in memory. You need an ORG that matches the offset portion. You will want to load the DS (and if need be the ES) with the segment portion (0x2000).

  • Before using string instructions like LODS/STOS/SCAS you want to ensure the Direction Flag (DF) is set the way you expect. Using CLD will set DF=0 for forward movement which is what your code expects.

  • It also appears that you call int 21h to print. It seems that code was left over from a DOS program and you meant to remove it.

  • You misspelled shutdown in the cmd_shut string. You incorrectly spelled it as shutdwon.

  • It is unclear what you wanted to do with this code:

      mov ah, 9      ; Unclear what you were trying to do here?
      mov bl, 9
      mov cx, 11
      int 10h        ; ????
    

You may wish to consider deleting it.

The beginning of your code could be modified to look like:

[bits 16]
ORG 0x0000

   mov ax, 0x2000 ; set up segments to match CS=0x2000
   mov ds, ax
   mov es, ax
   xor ax, ax
   mov ss, ax     ; set stack segment to 0x0000
   mov sp, 0x7C00 ; stack grows downwards from 0x0000:0x7C00
   cld            ; Clear Direction Flag (DF=0 is forward string movement)    

   mov ah, 9      ; Unclear what you were trying to do here?
   mov bl, 9
   mov cx, 11
   int 10h        ; ????

   mov si, boota  ; Print boot message
   call print_string
   [snip]

You spelled shutdown incorrectly so it won't be properly recognized as a command. It should be:

cmd_shut db 'shutdown', 0

With these changes the code looks like this when run:

这篇关于引导加载程序未加载内核的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆