I made a bootloader in assembly but it doesn't load the kernel, it also won't display any errors. My bootloader is as follows:
我用汇编语言做了一个引导加载程序,但它不能加载内核,也不会显示任何错误。我的引导加载程序如下所示:
org 7C00h ;start at
bits 16 ;16bit real mode
%define endl 0Dh, 0Ah
jmp strict short setup ;go back to your place bitch
nop
; FAT12 HEADER
bdb_oem: db 'MSWIN4.1' ; 8 bytes
bdb_bytes_per_sector: dw 512
bdb_sectors_per_cluster: db 1
bdb_reserved_sectors: dw 1
bdb_fat_count: db 2
bdb_dir_entries_count: dw 0E0h
bdb_total_sectors: dw 2880 ; 2880 * 512 = 1.44MB
bdb_media_descriptor_type: db 0F0h ; F0 = 3.5" floppy disk
bdb_sectors_per_fat: dw 9 ; 9 sectors/fat
bdb_sectors_per_track: dw 18
bdb_heads: dw 2
bdb_hidden_sectors: dd 0
bdb_large_sector_count: dd 0
; EBR SECTION
ebr_drive_number: db 0 ; 0x00 floppy, 0x80 hdd, useless
ebr_useless: db 0 ; reserved, windows stuff, i guess
ebr_signature: db 29h
ebr_volume_id: db 12h, 34h, 56h, 78h ; serial number, value doesn't matter
ebr_volume_label: db 'GOLD OS ' ; 11 bytes, padded with spaces
ebr_system_id: db 'FAT12 ' ; 8 bytes db 'FAT12 ' ; 8 bytes
; END OF HEADER
;MAIN AREA
;setup registers and stack
setup:
;setup registers
mov ax, 0 ;clear ax
mov ds, ax ;clear ds by copying ax
mov es,ax ;clear es by copying ax
;setup stack
mov ss, ax ;clear ss by copying ax
mov sp, 0x7c00 ;set stack to work without overwriting our stuff
;set disk number
mov [ebr_drive_number], dl
jmp kernel_find
;says shit
;PARAMS: si - String to print.
;RETURNS: nothing
talk:
;save registers to stack
push si
push ax
.loop:
lodsb ;load next character in al
or al, al ;verify if next character is null
jz .done ;if null then complete
;BIOS INTERRUPT, SEE RESOURCES.md
mov ah, 0eh ;print character
mov bh, 0 ;page 0
int 10h ;INTERRUPT VIDEO SERVICE
jmp .loop ;restart
.done:
pop ax
pop si
ret
;reboot function
reboot:
jmp 0FFFFh:0 ;jump to beginning of bios
;DISK AREA
;converts LBA(logical block addressing) address to CHS(cylinder, head, sector) address
;PARAMS: ax - LBA Address.
;RETURNS: cx[0-5] - Sector number.
; : cx[6-15] - Cylinder.
; : dh - Head.
disk_lba_chs_conversion:
;save registers that are used, but are not part of param or input
push ax
push dx
xor dx, dx ;clear dx register
div word [bdb_sectors_per_track] ;ax = LBA Address / Sectors per Track
;dx = LBA Address % Sectors per Track
inc dx ;dx = the previous operation + 1 = sector
mov cx, dx ;send to the correct output register
xor dx, dx ;clear dx
div word [bdb_heads] ;ax = (address / sectors per track) / Heads = cylinder
;dx = (address / sectors per track) % Heads = head
mov dh, dl ;send value to output location
;dl = lower 8 bits of dx
mov ch, al ;ye same shit
shl ah, 6 ;shift 6 bits to left
or cl, ah ;move the data, don't replace everything
; restore registers
pop ax
mov dl, al
pop ax
ret
floppy_error:
mov si, ferror_read_failed
call fatal_reboot
;reads the disk
;PARAMS: ax - LBA Address.
; : cl - nuber of sectors to read.
; : dl - drive number.
; : es:bx - memory address to store the data.
;RETURNS: (relative) - data read.
disk_read:
pusha ; save registers we will modify
push cx ; temporarily save CL (number of sectors to read)
call disk_lba_chs_conversion ; compute CHS
pop ax ; AL = number of sectors to read
mov ah, 02h
mov di, 3 ; retry count
.retry:
pusha ; save all registers, we don't know what bios modifies
stc ; set carry flag, some BIOS'es don't set it
int 13h ; carry flag cleared = success
popa
jnc .done ; jump if carry not set
; read failed
call disk_reset
dec di
test di, di
jnz .retry
.fail:
; all attempts are exhausted
jmp floppy_error
.done:
popa ; restore registers
ret
disk_reset:
pusha
mov ah, 0
stc
int 13h
jc floppy_error
popa
ret
;KERNEL LOAD AREA
KERNEL_LOAD_SEGMENT equ 0x2000
KERNEL_LOAD_OFFSET equ 0
kernel_cluster: dw 0
;just gets the size of the root directory
kernel_find:
;get root directory address
mov ax, [bdb_sectors_per_fat]
mov bl, [bdb_fat_count]
xor bh, bh
mul bx
add ax, [bdb_reserved_sectors]
push ax
;get size of root directory
mov ax, [bdb_sectors_per_fat]
shl ax, 5
xor dx, dx
div word [bdb_bytes_per_sector]
test dx, dx
jz .rdsdone
inc ax
.rdsdone:
;read root diretory
mov cl, al
pop ax
mov dl, [ebr_drive_number]
mov bx, buffer
call disk_read
;find the kernel
xor bx, bx
mov di, buffer
.kernelsearch:
mov si, file_kernel
mov cx, 11
push di
repe cmpsb
pop di
je .kernelfound
add di, 32
inc bx
cmp bx, [bdb_dir_entries_count]
jl .kernelsearch
mov si, ferror_no_kernel
call talk
call fatal_reboot
.kernelfound:
mov ax, [di + 26]
mov [kernel_cluster], ax
;get stuff from disk
mov ax, [bdb_reserved_sectors]
mov bx, buffer
mov cl, [bdb_sectors_per_fat]
mov dl, [ebr_drive_number]
call disk_read
mov bx, KERNEL_LOAD_SEGMENT
mov es, bx
mov bx, KERNEL_LOAD_OFFSET
.kernelload:
mov ax, [kernel_cluster]
;awfull shit, only safe in floppy disk
add ax, 31
mov cl, 1
mov dl, [ebr_drive_number]
call disk_read
add bx, [bdb_bytes_per_sector] ;awfull shit, will overflow if kernel above 64kb, will overwrite if it happens
mov ax, [kernel_cluster]
mov cx, 3
mul cx
mov cx, 2
div cx
mov si, buffer
add si, ax
mov ax, [ds:si]
or dx, dx
jz .even
.odd:
shr ax, 4
jmp .continue
.even:
and ax, 0x0FFF
.continue: ;didn't have a better name
cmp ax, 0x0FF8
jae .finishreading
mov [kernel_cluster], ax
jmp .kernelload
.finishreading: ;time to go to bed, hehe
mov dl, [ebr_drive_number]
mov ax, KERNEL_LOAD_SEGMENT
jmp KERNEL_LOAD_SEGMENT:KERNEL_LOAD_OFFSET ;goodbye
mov si, ferror_kernel_jump_failed
call fatal_reboot
ret
;STRING AREA
file_kernel: db "KERNEL BIN"
ferror_no_kernel: db "FATAL ERROR: Kernel Not Found", endl, 0
ferror_read_failed: db "FATAL ERROR: Disk read operation Failed", endl, 0 ;message for when it can't read the disk.
ferror_kernel_jump_failed: db "FATAL ERROR: Jump to Kernel Failed"
; MISC AREA
;reboots in case of fatal error
;PARAMS: si - error string
fatal_reboot:
call talk ;here just to gain a little bit of space
;BIOS INTERRUPT, SEE RESOURCES.md
mov ah, 0 ;wait for keypress
int 16h ;INTERRUPT KEYBOARD SERVICE
jmp reboot
ret
times 510-($-$$) db 0 ;nullify the rest of the 512 bytes we can use
dw 0AA55h ;bootloader signature, DO NOT TOUCH, DON'T EVEN THINK ABOUT IT.
;everything beyond this point will not be protected and can be overwritten by the stack, write at your own risk.
buffer: ;label to unused space
The kernel.asm I build into kernel.bin:
我在kernel.bin中构建的kernel.asm:
%define endl 0Dh, 0Ah
jmp main
;says shit
;PARAMS: si - String to print.
;RETURNS: nothing
talk:
;save registers to stack
push si
push ax
.loop:
lodsb ;load next character in al
or al, al ;verify if next character is null
jz .done ;if null then complete
;BIOS INTERRUPT, SEE RESOURCES.md
mov ah, 0eh ;print character
mov bh, 0 ;page 0
int 10h ;INTERRUPT VIDEO SERVICE
jmp .loop ;restart
.done:
pop ax
pop si
ret
main:
mov si, str_hello
call talk
str_hello: db "do u hav som ppsi", 0, endl
tried checking my makefile, swapped for a verified one, still, the problem persisted
replaced the kernel_find label for one that I know works, still nothing.
我试着检查了我的Makefile,换成了一个经过验证的Makefile,但问题仍然存在,用KERNEL_FIND标签替换了一个我知道有效的标签,仍然一无所获。
The "I know works" repo: nanobyte_os
“我知道有效”的回复:Nanobyte_os
更多回答
You never change ds
so it still has the value from the boot sector. Chances are, your kernel is loaded properly, it just doesn't find the str_hello
. Try mov ax, KERNEL_LOAD_SEGMENT; mov ds, ax
.
您永远不会更改DS,因此它仍然具有来自引导扇区的值。很有可能,您的内核已正确加载,只是找不到str_Hello。尝试使用mov ax、kernelad_Segment;mov ds、ax。
Not sure which pusha
you are referring to but the one on line 142 seems to have a matching popa
on line 145. The other one on line 132 has its counterpart on line 160.
不知道你指的是哪一个蒲莎,但第142行的那个似乎在第145行有一个匹配的Popa。线路132上的另一个与其对应的线路160上。
@jester I removed my comment after I realized the code he was now showing fixed the problem I identified in his previous question. Previously his kernel wouldn't load because his disk_read
would never return because popa
wasn't balanced.
@jester在我意识到他现在显示的代码解决了我在他之前的问题中发现的问题后,我删除了我的评论。以前,他的内核不会加载,因为因为Popa不平衡,所以他的DISK_READ永远不会返回。
Just a comment, nothing that will make or break your code, but the comment line: ; some BIOSes might start us at 07C0:0000 instead of 0000:7C00, make sure ; we are in the expected location
is a common misconception. As long as you do not use the cs: override and do not reference anything from the cs register, except for jmps and what not, you do not have to make sure the cs:ip register pair is correct. It can be 0x0010:7B00 as far as you are concerned. No need to change the cs:ip register pair unless you intend to use the cs: override, or other rare code that references cs.
只要不使用cs:覆盖,并且不引用cs寄存器中的任何内容,除了JMPS等等,就不必确保cs:ip寄存器对是正确的。就您而言,它可以是0x0010:7B00。不需要更改cs:ip寄存器对,除非您打算使用cs:override或其他罕见的引用cs的代码。
@fysnet. Relative and far jmps wouldn't be affected but one jmp that would be is a near indirect absolute jmp which uses CS implicitly.
@fysnet。相对jmp和远jmp不会受到影响,但会受到影响的一个jmp是隐式使用CS的近间接绝对jmp。
我是一名优秀的程序员,十分优秀!