引导加载程序未加载内核 [英] Bootloader is Not loading the kernel
问题描述
我正在开发我的操作系统.
我在启动操作系统时出错.
错误是:
<块引用>未找到 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 thecmd_shut
string. You incorrectly spelled it asshutdwon
.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屋!